1 /-
2 Copyright (c) 2015 Microsoft Corporation. All rights reserved.
3 Released under Apache 2.0 license as described in the file LICENSE.
4 Author: Mario Carneiro
5
6 Multisets.
7 -/
8 import logic.function order.boolean_algebra
src └────────────┘ └───────────────────┘
9 data.equiv.basic data.list.basic data.list.perm data.list.sort data.quot data.string.basic
src └──────────────┘ └─────────────┘ └────────────┘ └────────────┘ └───────┘ └───────────────┘
10 algebra.order_functions algebra.group_power algebra.ordered_group
src └─────────────────────┘ └─────────────────┘ └───────────────────┘
11 category.traversable.lemmas tactic.interactive
src └─────────────────────────┘ └────────────────┘
12 category.traversable.instances category.basic
src └────────────────────────────┘ └────────────┘
13
14 open list subtype nat lattice
15
16 variables {α : Type*} {β : Type*} {γ : Type*}
17
18 open_locale add_monoid
19
20 /-- `multiset α` is the quotient of `list α` by list permutation. The result
21 is a type of finite sets with duplicates allowed. -/
22 def {u} multiset (α : Type u) : Type u :=
23 quotient (list.is_setoid α)
id └──────┘ └────────────┘ ┴
src └──────┘ └────────────┘
typ └──────┘ └────────────┘ ┴
24
25 namespace multiset
26
27 instance : has_coe (list α) (multiset α) := ⟨quot.mk _⟩
id └─────┘ └──┘ ┴ └──────┘ ┴ └─────┘
src └─────┘ └──┘ └──────┘
typ └─────┘ └──┘ ┴ └──────┘ ┴ └─────┘
doc └──────┘
28
29 @[simp] theorem quot_mk_to_coe (l : list α) : @eq (multiset α) ⟦l⟧ l := rfl
id └──┘ ┴ └┘ └──────┘ ┴ ┴┴┴ ┴ └─┘
src └──┘ └┘ └──────┘ ┴ ┴ └─┘
typ └──┘ ┴ └┘ └──────┘ ┴ ┴┴┴ ┴ └─┘
doc └──┘ └──────┘
30
31 @[simp] theorem quot_mk_to_coe' (l : list α) : @eq (multiset α) (quot.mk (≈) l) l := rfl
id └──┘ ┴ └┘ └──────┘ ┴ └─────┘ ┴ ┴ ┴ └─┘
src └──┘ └┘ └──────┘ ┴ └─┘
typ └──┘ ┴ └┘ └──────┘ ┴ └─────┘ ┴ ┴ ┴ └─┘
doc └──┘ └──────┘
32
33 @[simp] theorem quot_mk_to_coe'' (l : list α) : @eq (multiset α) (quot.mk setoid.r l) l := rfl
id └──┘ ┴ └┘ └──────┘ ┴ └─────┘ └──────┘ ┴ ┴ └─┘
src └──┘ └┘ └──────┘ └──────┘ └─┘
typ └──┘ ┴ └┘ └──────┘ ┴ └─────┘ └──────┘ ┴ ┴ └─┘
doc └──┘ └──────┘
34
35 @[simp] theorem coe_eq_coe {l₁ l₂ : list α} : (l₁ : multiset α) = l₂ ↔ l₁ ~ l₂ := quotient.eq
id └──┘ ┴ └┘ └──────┘ ┴ ┴ └┘ ┴ └┘ ┴ └┘ └─────────┘
src └──┘ └──────┘ ┴ ┴ ┴ └─────────┘
typ └──┘ ┴ └┘ └──────┘ ┴ ┴ └┘ ┴ └┘ ┴ └┘ └─────────┘
doc └──┘ └──────┘ ┴
36
37 instance has_decidable_eq [decidable_eq α] : decidable_eq (multiset α)
id └──────────┘ ┴ └──────────┘ └──────┘ ┴
src └──────────┘ └──────────┘ └──────┘
typ └──────────┘ ┴ └──────────┘ └──────┘ ┴
doc └──────┘
38 | s₁ s₂ := quotient.rec_on_subsingleton₂ s₁ s₂ $ λ l₁ l₂,
id └┘ └┘ └───────────────────────────┘ └┘ └┘
src └───────────────────────────┘
typ └┘ └┘ └───────────────────────────┘ └┘ └┘
39 decidable_of_iff' _ quotient.eq
id └───────────────┘ └─────────┘
src └───────────────┘ └─────────┘
typ └───────────────┘ └─────────┘
40
41 /- empty multiset -/
42
43 /-- `0 : multiset α` is the empty set -/
44 protected def zero : multiset α := @nil α
id └──────┘ ┴ └─┘ ┴
src └──────┘ └─┘
typ └──────┘ ┴ └─┘ ┴
doc └──────┘
45
46 instance : has_zero (multiset α) := ⟨multiset.zero⟩
id └──────┘ └──────┘ ┴ └───────────┘
src └──────┘ └──────┘ └───────────┘
typ └──────┘ └──────┘ ┴ └───────────┘
doc └──────┘ └───────────┘
47 instance : has_emptyc (multiset α) := ⟨0⟩
id └────────┘ └──────┘ ┴
src └────────┘ └──────┘
typ └────────┘ └──────┘ ┴
doc └──────┘
48 instance : inhabited (multiset α) := ⟨0⟩
id └───────┘ └──────┘ ┴
src └───────┘ └──────┘
typ └───────┘ └──────┘ ┴
doc └──────┘
49
50 @[simp] theorem coe_nil_eq_zero : (@nil α : multiset α) = 0 := rfl
id └─┘ ┴ └──────┘ ┴ ┴ └─┘
src └─┘ └──────┘ ┴ └─┘
typ └─┘ ┴ └──────┘ ┴ ┴ └─┘
doc └──┘ └──────┘
51 @[simp] theorem empty_eq_zero : (∅ : multiset α) = 0 := rfl
id ┴ └──────┘ ┴ ┴ └─┘
src ┴ └──────┘ ┴ └─┘
typ ┴ └──────┘ ┴ ┴ └─┘
doc └──┘ └──────┘
52
53 theorem coe_eq_zero (l : list α) : (l : multiset α) = 0 ↔ l = [] :=
id └──┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘
src └──┘ └──────┘ ┴ ┴ ┴ └┘
typ └──┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘
doc └──────┘
54 iff.trans coe_eq_coe perm_nil
id └───────┘ └────────┘ └──────┘
src └───────┘ └────────┘ └──────┘
typ └───────┘ └────────┘ └──────┘
55
56 /- cons -/
57
58 /-- `cons a s` is the multiset which contains `s` plus one more
59 instance of `a`. -/
60 def cons (a : α) (s : multiset α) : multiset α :=
id ┴ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
61 quot.lift_on s (λ l, (a :: l : multiset α))
id └──────────┘ ┴ ┴ ┴ └┘ ┴ └──────┘ ┴
src └──────────┘ └┘ └──────┘
typ └──────────┘ ┴ ┴ ┴ └┘ ┴ └──────┘ ┴
doc └──────┘
62 (λ l₁ l₂ p, quot.sound ((perm_cons a).2 p))
id └┘ └┘ ┴ └────────┘ └───────┘ ┴ ┴ ┴
src └────────┘ └───────┘ ┴
typ └┘ └┘ ┴ └────────┘ └───────┘ ┴ ┴ ┴
63
64 notation a :: b := cons a b
id └──┘
src └──┘
typ └──┘
doc └──┘
65
66 instance : has_insert α (multiset α) := ⟨cons⟩
id └────────┘ ┴ └──────┘ ┴ └──┘
src └────────┘ └──────┘ └──┘
typ └────────┘ ┴ └──────┘ ┴ └──┘
doc └──────┘ └──┘
67
68 @[simp] theorem insert_eq_cons (a : α) (s : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
69 insert a s = a::s := rfl
id └────┘ ┴ ┴ ┴ ┴└┘┴ └─┘
src └────┘ ┴ └┘ └─┘
typ └────┘ ┴ ┴ ┴ ┴└┘┴ └─┘
doc └┘
70
71 @[simp] theorem cons_coe (a : α) (l : list α) :
id ┴ └──┘ ┴
src └──┘
typ ┴ └──┘ ┴
doc └──┘
72 (a::l : multiset α) = (a::l : list α) := rfl
id ┴└┘┴ └──────┘ ┴ ┴ ┴└┘┴ └──┘ ┴ └─┘
src └┘ └──────┘ ┴ └┘ └──┘ └─┘
typ ┴└┘┴ └──────┘ ┴ ┴ ┴└┘┴ └──┘ ┴ └─┘
doc └┘ └──────┘
73
74 theorem singleton_coe (a : α) : (a::0 : multiset α) = ([a] : list α) := rfl
id ┴ ┴└┘ └──────┘ ┴ ┴ ┴┴┴ └──┘ ┴ └─┘
src └┘ └──────┘ ┴ ┴ ┴ └──┘ └─┘
typ ┴ ┴└┘ └──────┘ ┴ ┴ ┴┴┴ └──┘ ┴ └─┘
doc └┘ └──────┘
75
76 @[simp] theorem cons_inj_left {a b : α} (s : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
77 a::s = b::s ↔ a = b :=
id ┴└┘┴ ┴ ┴└┘┴ ┴ ┴ ┴ ┴
src └┘ ┴ └┘ ┴ ┴
typ ┴└┘┴ ┴ ┴└┘┴ ┴ ┴ ┴ ┴
doc └┘ └┘
78 ⟨quot.induction_on s $ λ l e,
id └───────────────┘ ┴ ┴ ┴
src └───────────────┘
typ └───────────────┘ ┴ ┴ ┴
79 have [a] ++ l ~ [b] ++ l, from quotient.exact e,
id ┴┴┴ └┘ ┴ ┴ ┴┴┴ └┘ ┴ └────────────┘ ┴
src ┴ ┴ └┘ ┴ ┴ ┴ └┘ └────────────┘
typ ┴┴┴ └┘ ┴ ┴ ┴┴┴ └┘ ┴ └────────────┘ ┴
doc ┴
80 eq_singleton_of_perm $ (perm_app_right_iff _).1 this, congr_arg _⟩
id └──────────────────┘ └────────────────┘ ┴ └──┘ └───────┘
src └──────────────────┘ └────────────────┘ ┴ └───────┘
typ └──────────────────┘ └────────────────┘ ┴ └──┘ └───────┘
81
82 @[simp] theorem cons_inj_right (a : α) : ∀{s t : multiset α}, a::s = a::t ↔ s = t :=
id ┴ └──────┘ ┴ ┴└┘┴ ┴ ┴└┘┴ ┴ ┴ ┴ ┴
src └──────┘ └┘ ┴ └┘ ┴ ┴
typ ┴ └──────┘ ┴ ┴└┘┴ ┴ ┴└┘┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └┘ └┘
83 by rintros ⟨l₁⟩ ⟨l₂⟩; simp [perm_cons]
id └───────┘
src └───────────────┘ └────┘└───────┘└─
typ └───────────────┘ └────┘└───────┘└─
doc └───────────────┘ └────┘ └─
txt └───────────────┘ └────┘ └─
par └───────────────┘ └────┘ └─
pid └────────┘ ┴┴ ┴└
st └────────────────────────────────────
84
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
85 @[recursor 5] protected theorem induction {p : multiset α → Prop}
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘ └──────┘
86 (h₁ : p 0) (h₂ : ∀ ⦃a : α⦄ {s : multiset α}, p s → p (a :: s)) : ∀s, p s :=
id ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴
src └──────┘ └┘
typ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴
doc └──────┘ └┘
87 by rintros ⟨l⟩; induction l with _ _ ih; [exact h₁, exact h₂ ih]
id ┴ ┴ └┘ └┘ └┘
src └─────────┘ └────────┘ └──────────┘ ┴└────┘ └────┘ ┴
typ └─────────┘ └────────┘┴└──────────┘ ┴└────┘└┘ └────┘└┘┴└┘
doc └─────────┘ └────────┘ └──────────┘ └────┘ └────┘ ┴
txt └─────────┘ └────────┘ └──────────┘ └────┘ └────┘ ┴
par └─────────┘ └────────┘ └──────────┘ └────┘ └────┘ ┴
pid └──┘ ┴ ┴└─────────┘ ┴ ┴ ┴
st └────────────────────────────────────────────────────────────┘
88
89 @[elab_as_eliminator] protected theorem induction_on {p : multiset α → Prop}
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └────────────────┘ └──────┘
90 (s : multiset α) (h₁ : p 0) (h₂ : ∀ ⦃a : α⦄ {s : multiset α}, p s → p (a :: s)) : p s :=
id └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
src └──────┘ └──────┘ └┘
typ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
doc └──────┘ └──────┘ └┘
91 multiset.induction h₁ h₂ s
id └────────────────┘ └┘ └┘ ┴
src └────────────────┘
typ └────────────────┘ └┘ └┘ ┴
92
93 theorem cons_swap (a b : α) (s : multiset α) : a :: b :: s = b :: a :: s :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ └┘ ┴ ┴ ┴ └┘ ┴ └┘ ┴
src └──────┘ └┘ └┘ ┴ └┘ └┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ └┘ ┴ ┴ ┴ └┘ ┴ └┘ ┴
doc └──────┘ └┘ └┘ └┘ └┘
94 quot.induction_on s $ λ l, quotient.sound $ perm.swap _ _ _
id └───────────────┘ ┴ ┴ └────────────┘ └───────┘
src └───────────────┘ └────────────┘ └───────┘
typ └───────────────┘ ┴ ┴ └────────────┘ └───────┘
95
96 section rec
97 variables {C : multiset α → Sort*}
id └──────┘
src └──────┘
typ └──────┘
doc └──────┘
98
99 /-- Dependent recursor on multisets.
100
101 TODO: should be @[recursor 6], but then the definition of `multiset.pi` failes with a stack
102 overflow in `whnf`.
103 -/
104 protected def rec
105 (C_0 : C 0)
id ┴
typ ┴
106 (C_cons : Πa m, C m → C (a::m))
id ┴ ┴ ┴ ┴ ┴ ┴└┘┴
src └┘
typ ┴ ┴ ┴ ┴ ┴ ┴└┘┴
doc └┘
107 (C_cons_heq : ∀a a' m b, C_cons a (a'::m) (C_cons a' m b) == C_cons a' (a::m) (C_cons a m b))
id ┴ └┘ ┴ ┴ └────┘ ┴ └┘└┘┴ └────┘ └┘ ┴ ┴ └┘ └────┘ └┘ ┴└┘┴ └────┘ ┴ ┴ ┴
src └┘ └┘ └┘
typ ┴ └┘ ┴ ┴ └────┘ ┴ └┘└┘┴ └────┘ └┘ ┴ ┴ └┘ └────┘ └┘ ┴└┘┴ └────┘ ┴ ┴ ┴
doc └┘ └┘
108 (m : multiset α) : C m :=
id └──────┘ ┴ ┴ ┴
src └──────┘
typ └──────┘ ┴ ┴ ┴
doc └──────┘
109 quotient.hrec_on m (@list.rec α (λl, C ⟦l⟧) C_0 (λa l b, C_cons a ⟦l⟧ b)) $
id └──────────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴┴┴ └─┘ ┴ ┴ ┴ └────┘ ┴ ┴┴┴ ┴
src └──────────────┘ └──────┘ ┴ ┴ ┴ ┴
typ └──────────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴┴┴ └─┘ ┴ ┴ ┴ └────┘ ┴ ┴┴┴ ┴
110 assume l l' h,
id ┴ └┘ ┴
typ ┴ └┘ ┴
111 list.rec_heq_of_perm h
id └──────────────────┘ ┴
src └──────────────────┘
typ └──────────────────┘ ┴
112 (assume a l l' b b' hl, have ⟦l⟧ = ⟦l'⟧, from quot.sound hl, by cc)
id ┴ ┴ └┘ ┴ └┘ └┘ ┴┴┴ ┴ ┴└┘┴ └────────┘ └┘
src ┴ ┴ ┴ ┴ ┴ └────────┘ └┘
typ ┴ ┴ └┘ ┴ └┘ └┘ ┴┴┴ ┴ ┴└┘┴ └────────┘ └┘ └┘
doc └┘
txt └┘
par └┘
st └─┘
113 (assume a a' l, C_cons_heq a a' ⟦l⟧)
id ┴ └┘ ┴ └────────┘ ┴ └┘ ┴┴┴
src ┴ ┴
typ ┴ └┘ ┴ └────────┘ ┴ └┘ ┴┴┴
114
115 @[elab_as_eliminator]
doc └────────────────┘
116 protected def rec_on (m : multiset α)
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
117 (C_0 : C 0)
id ┴
typ ┴
118 (C_cons : Πa m, C m → C (a::m))
id ┴ ┴ ┴ ┴ ┴ ┴└┘┴
src └┘
typ ┴ ┴ ┴ ┴ ┴ ┴└┘┴
doc └┘
119 (C_cons_heq : ∀a a' m b, C_cons a (a'::m) (C_cons a' m b) == C_cons a' (a::m) (C_cons a m b)) :
id ┴ └┘ ┴ ┴ └────┘ ┴ └┘└┘┴ └────┘ └┘ ┴ ┴ └┘ └────┘ └┘ ┴└┘┴ └────┘ ┴ ┴ ┴
src └┘ └┘ └┘
typ ┴ └┘ ┴ ┴ └────┘ ┴ └┘└┘┴ └────┘ └┘ ┴ ┴ └┘ └────┘ └┘ ┴└┘┴ └────┘ ┴ ┴ ┴
doc └┘ └┘
120 C m :=
id ┴ ┴
typ ┴ ┴
121 multiset.rec C_0 C_cons C_cons_heq m
id └──────────┘ └─┘ └────┘ └────────┘ ┴
src └──────────┘
typ └──────────┘ └─┘ └────┘ └────────┘ ┴
doc └──────────┘
122
123 variables {C_0 : C 0} {C_cons : Πa m, C m → C (a::m)}
id ┴ ┴ ┴ ┴ ┴└┘┴
src └┘
typ ┴ ┴ ┴ ┴ ┴└┘┴
doc └┘
124 {C_cons_heq : ∀a a' m b, C_cons a (a'::m) (C_cons a' m b) == C_cons a' (a::m) (C_cons a m b)}
id ┴ └┘ ┴ ┴ ┴ └┘└┘┴ └┘ ┴ ┴ └┘ └┘ ┴└┘┴ ┴ ┴ ┴
src └┘ └┘ └┘
typ ┴ └┘ ┴ ┴ ┴ └┘└┘┴ └┘ ┴ ┴ └┘ └┘ ┴└┘┴ ┴ ┴ ┴
doc └┘ └┘
125
126 @[simp] lemma rec_on_0 : @multiset.rec_on α C (0:multiset α) C_0 C_cons C_cons_heq = C_0 :=
id └─────────────┘ ┴ ┴ └──────┘ ┴ └─┘ └────┘ └────────┘ ┴ └─┘
src └─────────────┘ └──────┘ ┴
typ └─────────────┘ ┴ ┴ └──────┘ ┴ └─┘ └────┘ └────────┘ ┴ └─┘
doc └──┘ └──────┘
127 rfl
id └─┘
src └─┘
typ └─┘
128
129 @[simp] lemma rec_on_cons (a : α) (m : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
130 (a :: m).rec_on C_0 C_cons C_cons_heq = C_cons a m (m.rec_on C_0 C_cons C_cons_heq) :=
id ┴ └┘ ┴ └────┘ └─┘ └────┘ └────────┘ ┴ └────┘ ┴ ┴ ┴└─────┘ └─┘ └────┘ └────────┘
src └┘ └────┘ ┴ └─────┘
typ ┴ └┘ ┴ └────┘ └─┘ └────┘ └────────┘ ┴ └────┘ ┴ ┴ ┴└─────┘ └─┘ └────┘ └────────┘
doc └┘
131 quotient.induction_on m $ assume l, rfl
id └───────────────────┘ ┴ ┴ └─┘
src └───────────────────┘ └─┘
typ └───────────────────┘ ┴ ┴ └─┘
132
133 end rec
134
135 section mem
136
137 /-- `a ∈ s` means that `a` has nonzero multiplicity in `s`. -/
138 def mem (a : α) (s : multiset α) : Prop :=
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──────┘
139 quot.lift_on s (λ l, a ∈ l) (λ l₁ l₂ (e : l₁ ~ l₂), propext $ mem_of_perm e)
id └──────────┘ ┴ ┴ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └┘ └─────┘ └─────────┘ ┴
src └──────────┘ ┴ ┴ └─────┘ └─────────┘
typ └──────────┘ ┴ ┴ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └┘ └─────┘ └─────────┘ ┴
doc ┴
140
141 instance : has_mem α (multiset α) := ⟨mem⟩
id └─────┘ ┴ └──────┘ ┴ └─┘
src └─────┘ └──────┘ └─┘
typ └─────┘ ┴ └──────┘ ┴ └─┘
doc └──────┘ └─┘
142
143 @[simp] lemma mem_coe {a : α} {l : list α} : a ∈ (l : multiset α) ↔ a ∈ l := iff.rfl
id ┴ └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └─────┘
src └──┘ ┴ └──────┘ ┴ ┴ └─────┘
typ ┴ └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └─────┘
doc └──┘ └──────┘
144
145 instance decidable_mem [decidable_eq α] (a : α) (s : multiset α) : decidable (a ∈ s) :=
id └──────────┘ ┴ ┴ └──────┘ ┴ └───────┘ ┴ ┴ ┴
src └──────────┘ └──────┘ └───────┘ ┴
typ └──────────┘ ┴ ┴ └──────┘ ┴ └───────┘ ┴ ┴ ┴
doc └──────┘
146 quot.rec_on_subsingleton s $ list.decidable_mem a
id └──────────────────────┘ ┴ └────────────────┘ ┴
src └──────────────────────┘ └────────────────┘
typ └──────────────────────┘ ┴ └────────────────┘ ┴
147
148 @[simp] theorem mem_cons {a b : α} {s : multiset α} : a ∈ b :: s ↔ a = b ∨ a ∈ s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └┘ ┴ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └┘
149 quot.induction_on s $ λ l, iff.rfl
id └───────────────┘ ┴ ┴ └─────┘
src └───────────────┘ └─────┘
typ └───────────────┘ ┴ ┴ └─────┘
150
151 lemma mem_cons_of_mem {a b : α} {s : multiset α} (h : a ∈ s) : a ∈ b :: s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ ┴ └┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘
152 mem_cons.2 $ or.inr h
id └──────┘┴ └────┘ ┴
src └──────┘┴ └────┘
typ └──────┘┴ └────┘ ┴
153
154 @[simp] theorem mem_cons_self (a : α) (s : multiset α) : a ∈ a :: s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ └┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴
doc └──┘ └──────┘ └┘
155 mem_cons.2 (or.inl rfl)
id └──────┘┴ └────┘ └─┘
src └──────┘┴ └────┘ └─┘
typ └──────┘┴ └────┘ └─┘
156
157 theorem exists_cons_of_mem {s : multiset α} {a : α} : a ∈ s → ∃ t, s = a :: t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ ┴ ┴ ┴ └┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘
158 quot.induction_on s $ λ l (h : a ∈ l),
id └───────────────┘ ┴ ┴ ┴ ┴ ┴
src └───────────────┘ ┴
typ └───────────────┘ ┴ ┴ ┴ ┴ ┴
159 let ⟨l₁, l₂, e⟩ := mem_split h in
id └─┘ └┘ └┘ ┴ └───────┘ ┴
src └───────┘
typ └─┘ └┘ └┘ ┴ └───────┘ ┴
160 e.symm ▸ ⟨(l₁++l₂ : list α), quot.sound perm_middle⟩
id └───┘ ┴ └┘ └──┘ ┴ └────────┘ └─────────┘
src └───┘ ┴ └┘ └──┘ └────────┘ └─────────┘
typ └───┘ ┴ └┘ └──┘ ┴ └────────┘ └─────────┘
161
162 @[simp] theorem not_mem_zero (a : α) : a ∉ (0 : multiset α) := id
id ┴ ┴ ┴ └──────┘ ┴ └┘
src ┴ └──────┘ └┘
typ ┴ ┴ ┴ └──────┘ ┴ └┘
doc └──┘ └──────┘
163
164 theorem eq_zero_of_forall_not_mem {s : multiset α} : (∀x, x ∉ s) → s = 0 :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
165 quot.induction_on s $ λ l H, by rw eq_nil_iff_forall_not_mem.mpr H; refl
id └───────────────┘ ┴ ┴ ┴ └───────────────────────────┘ ┴
src └───────────────┘ └─┘└───────────────────────────┘┴ └────
typ └───────────────┘ ┴ ┴ ┴ └─┘└───────────────────────────┘┴┴ └────
doc └─┘ ┴ └────
txt └─┘ ┴ └────
par └─┘ ┴ └────
pid ┴ ┴ └
st └─────────────────────────────────────────
166
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
167 theorem eq_zero_iff_forall_not_mem {s : multiset α} : s = 0 ↔ ∀ a, a ∉ s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
168 ⟨λ h, h.symm ▸ λ _, not_false, eq_zero_of_forall_not_mem⟩
id ┴ ┴└───┘ ┴ ┴ └───────┘ └───────────────────────┘
src └───┘ ┴ └───────┘ └───────────────────────┘
typ ┴ ┴└───┘ ┴ ┴ └───────┘ └───────────────────────┘
169
170 theorem exists_mem_of_ne_zero {s : multiset α} : s ≠ 0 → ∃ a : α, a ∈ s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
doc └──────┘
171 quot.induction_on s $ assume l hl,
id └───────────────┘ ┴ ┴ └┘
src └───────────────┘
typ └───────────────┘ ┴ ┴ └┘
172 match l, hl with
id ┴ └┘
typ ┴ └┘
173 | [] := assume h, false.elim $ h rfl
id └┘ ┴ └────────┘ ┴ └─┘
src └┘ └────────┘ └─┘
typ └┘ ┴ └────────┘ ┴ └─┘
174 | (a :: l) := assume _, ⟨a, by simp⟩
id ┴ └┘ ┴
src └┘ └──┘
typ ┴ └┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
175 end
176
177 @[simp] lemma zero_ne_cons {a : α} {m : multiset α} : 0 ≠ a :: m :=
id ┴ └──────┘ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ └┘
typ ┴ └──────┘ ┴ ┴ ┴ └┘ ┴
doc └──┘ └──────┘ └┘
178 assume h, have a ∈ (0:multiset α), from h.symm ▸ mem_cons_self _ _, not_mem_zero _ this
id ┴ ┴ ┴ └──────┘ ┴ ┴└───┘ ┴ └───────────┘ └──────────┘ └──┘
src ┴ └──────┘ └───┘ ┴ └───────────┘ └──────────┘
typ ┴ ┴ ┴ └──────┘ ┴ ┴└───┘ ┴ └───────────┘ └──────────┘ └──┘
doc └──────┘
179
180 @[simp] lemma cons_ne_zero {a : α} {m : multiset α} : a :: m ≠ 0 := zero_ne_cons.symm
id ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ └──────────┘└───┘
src └──────┘ └┘ ┴ └──────────┘└───┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ └──────────┘└───┘
doc └──┘ └──────┘ └┘
181
182 lemma cons_eq_cons {a b : α} {as bs : multiset α} :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──────┘
183 a :: as = b :: bs ↔ ((a = b ∧ as = bs) ∨ (a ≠ b ∧ ∃cs, as = b :: cs ∧ bs = a :: cs)) :=
id ┴ └┘ └┘ ┴ ┴ └┘ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴└┘┴ └┘ ┴ ┴ └┘ └┘ ┴ └┘ ┴ ┴ └┘ └┘
src └┘ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘
typ ┴ └┘ └┘ ┴ ┴ └┘ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴└┘┴ └┘ ┴ ┴ └┘ └┘ ┴ └┘ ┴ ┴ └┘ └┘
doc └┘ └┘ └┘ └┘
184 begin
st └─────
185 haveI : decidable_eq α := classical.dec_eq α,
id └──────────┘ ┴ └──────────────┘ ┴
src └──────┘└──────────┘┴ └──┘└──────────────┘┴
typ └──────┘└──────────┘┴┴└──┘└──────────────┘┴┴
doc └──────┘ ┴ └──┘ ┴
txt └──────┘ ┴ └──┘ ┴
par └──────┘ ┴ └──┘ ┴
pid ┴└┘ ┴ └──┘ ┴
st ─────────────────────────────────────────────┘└─
186 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ──────┘└─
187 { assume eq,
src └───────┘
typ └───────┘
doc └───────┘
txt └───────┘
par └───────┘
pid └───────┘
st ───┘└───────┘└─
188 by_cases a = b,
id ┴ ┴ ┴
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ─────────────────┘└─
189 { subst h, simp * at * },
id ┴
src └────┘ └──────────┘
typ └────┘┴ └──────────┘
doc └────┘ └──────────┘
txt └────┘ └──────────┘
par └────┘ └──────────┘
pid ┴ ┴┴┴└──┘┴
st ─────┘└─────┘└────────────┘└┘└
190 { have : a ∈ b :: bs, from eq ▸ mem_cons_self _ _,
id ┴ ┴ ┴ └┘ └┘ └┘ ┴ └───────────┘
src └─────┘ ┴┴┴ ┴└┘┴ └───┘└┘┴┴┴└───────────┘└──┘
typ └─────┘┴┴┴┴┴┴└┘┴└┘ └───┘└┘┴┴┴└───────────┘└──┘
doc └─────┘ ┴ ┴ ┴└┘┴ └───┘ ┴ ┴ └──┘
txt └─────┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └──┘
par └─────┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └──┘
pid └───┘└┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └──┘
st ───────────────────────┘└───────────────────────────┘└─
191 have : a ∈ bs, by simpa [h],
id ┴ └┘ ┴
src └─────┘ ┴ ┴ └─────┘ ┴
typ └─────┘┴┴ ┴└┘ └─────┘┴┴
doc └─────┘ ┴ ┴ └─────┘ ┴
txt └─────┘ ┴ ┴ └─────┘ ┴
par └─────┘ ┴ ┴ └─────┘ ┴
pid └───┘└┘ ┴ ┴ ┴┴ ┴
st ──────────────────┘ └─
192 rcases exists_cons_of_mem this with ⟨cs, hcs⟩,
id └────────────────┘ └──┘
src └─────┘└────────────────┘┴ └─────────────┘
typ └─────┘└────────────────┘┴└──┘└─────────────┘
doc └─────┘ ┴ └─────────────┘
txt └─────┘ ┴ └─────────────┘
par └─────┘ ┴ └─────────────┘
pid ┴ ┴ └─────────────┘
st ──────────────────────────────────────────────────┘└─
193 simp [h, hcs],
id ┴ └─┘
src └────┘ └┘ ┴
typ └────┘┴└┘└─┘┴
doc └────┘ └┘ ┴
txt └────┘ └┘ ┴
par └────┘ └┘ ┴
pid ┴┴ └┘ ┴
st ──────────────────┘└─
194 have : a :: as = b :: a :: cs, by simp [eq, hcs],
id └┘ ┴ ┴ └┘ └┘ └─┘
src └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘└┘└┘ ┴
typ └─────┘ ┴ ┴└┘┴ ┴┴┴ ┴┴┴ ┴└┘ └────┘└┘└┘└─┘┴
doc └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ └┘ ┴
txt └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ └┘ ┴
par └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ └┘ ┴
pid └───┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ └┘ ┴
st ──────────────────────────────────┘ └─
195 have : a :: as = a :: b :: cs, by rwa [cons_swap],
id └┘ ┴ ┴ └┘ └───────┘
src └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘└───────┘┴
typ └─────┘ ┴ ┴└┘┴ ┴┴┴ ┴┴┴ ┴└┘ └───┘└───────┘┴
doc └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴
txt └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴
par └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴
pid └───┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
st ──────────────────────────────────┘ └───────┘┴└─
196 simpa using this } },
id └──┘
src └──────────┘ ┴
typ └──────────┘└──┘┴
doc └──────────┘ ┴
txt └──────────┘ ┴
par └──────────┘ ┴
pid ┴└────┘ ┴
st ──────────────────────┘└──┘└
197 { assume h,
src └──────┘
typ └──────┘
doc └──────┘
txt └──────┘
par └──────┘
pid └──────┘
st ───────────┘└─
198 rcases h with ⟨eq₁, eq₂⟩ | ⟨h, cs, eq₁, eq₂⟩,
id ┴
src └─────┘ └──────────────────────────────────┘
typ └─────┘┴└──────────────────────────────────┘
doc └─────┘ └──────────────────────────────────┘
txt └─────┘ └──────────────────────────────────┘
par └─────┘ └──────────────────────────────────┘
pid ┴ └──────────────────────────────────┘
st ───────────────────────────────────────────────┘└─
199 { simp * },
src └─────┘
typ └─────┘
doc └─────┘
txt └─────┘
par └─────┘
pid ┴┴┴
st ─────┘└─────┘└┘└
200 { simp [*, cons_swap a b] } }
id └───────┘ ┴ ┴
src └───────┘└───────┘┴ ┴ └┘
typ └───────┘└───────┘┴┴┴┴└┘
doc └───────┘ ┴ ┴ └┘
txt └───────┘ ┴ ┴ └┘
par └───────┘ ┴ ┴ └┘
pid ┴└──┘ ┴ ┴ ┴┴
st ─────────────────────────────┘└───
201 end
st ──┘
202
203 end mem
204
205 /- subset -/
206 section subset
207
208 /-- `s ⊆ t` is the lift of the list subset relation. It means that any
209 element with nonzero multiplicity in `s` has nonzero multiplicity in `t`,
210 but it does not imply that the multiplicity of `a` in `s` is less or equal than in `t`;
211 see `s ≤ t` for this relation. -/
212 protected def subset (s t : multiset α) : Prop := ∀ ⦃a : α⦄, a ∈ s → a ∈ t
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
213
214 instance : has_subset (multiset α) := ⟨multiset.subset⟩
id └────────┘ └──────┘ ┴ └─────────────┘
src └────────┘ └──────┘ └─────────────┘
typ └────────┘ └──────┘ ┴ └─────────────┘
doc └──────┘ └─────────────┘
215
216 @[simp] theorem coe_subset {l₁ l₂ : list α} : (l₁ : multiset α) ⊆ l₂ ↔ l₁ ⊆ l₂ := iff.rfl
id └──┘ ┴ └┘ └──────┘ ┴ ┴ └┘ ┴ └┘ ┴ └┘ └─────┘
src └──┘ └──────┘ ┴ ┴ ┴ └─────┘
typ └──┘ ┴ └┘ └──────┘ ┴ ┴ └┘ ┴ └┘ ┴ └┘ └─────┘
doc └──┘ └──────┘
217
218 @[simp] theorem subset.refl (s : multiset α) : s ⊆ s := λ a h, h
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
219
220 theorem subset.trans {s t u : multiset α} : s ⊆ t → t ⊆ u → s ⊆ u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
221 λ h₁ h₂ a m, h₂ (h₁ m)
id └┘ └┘ ┴ ┴ └┘ └┘ ┴
typ └┘ └┘ ┴ ┴ └┘ └┘ ┴
222
223 theorem subset_iff {s t : multiset α} : s ⊆ t ↔ (∀⦃x⦄, x ∈ s → x ∈ t) := iff.rfl
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘
src └──────┘ ┴ ┴ ┴ ┴ └─────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘
doc └──────┘
224
225 theorem mem_of_subset {s t : multiset α} {a : α} (h : s ⊆ t) : a ∈ s → a ∈ t := @h _
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
226
227 @[simp] theorem zero_subset (s : multiset α) : 0 ⊆ s :=
id └──────┘ ┴ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴ ┴
doc └──┘ └──────┘
228 λ a, (not_mem_nil a).elim
id ┴ └─────────┘ ┴ └──┘
src └─────────┘ └──┘
typ ┴ └─────────┘ ┴ └──┘
229
230 @[simp] theorem cons_subset {a : α} {s t : multiset α} : (a :: s) ⊆ t ↔ a ∈ t ∧ s ⊆ t :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └┘ ┴ ┴ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └┘
231 by simp [subset_iff, or_imp_distrib, forall_and_distrib]
id └────────┘ └────────────┘ └────────────────┘
src └────┘└────────┘└┘└────────────┘└┘└────────────────┘└─
typ └────┘└────────┘└┘└────────────┘└┘└────────────────┘└─
doc └────┘ └┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └──────────────────────────────────────────────────────
232
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
233 theorem eq_zero_of_subset_zero {s : multiset α} (h : s ⊆ 0) : s = 0 :=
id └──────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘
234 eq_zero_of_forall_not_mem h
id └───────────────────────┘ ┴
src └───────────────────────┘
typ └───────────────────────┘ ┴
235
236 theorem subset_zero {s : multiset α} : s ⊆ 0 ↔ s = 0 :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
237 ⟨eq_zero_of_subset_zero, λ xeq, xeq.symm ▸ subset.refl 0⟩
id └────────────────────┘ └─┘ └─┘└───┘ ┴ └─────────┘
src └────────────────────┘ └───┘ ┴ └─────────┘
typ └────────────────────┘ └─┘ └─┘└───┘ ┴ └─────────┘
238
239 end subset
240
241 /- multiset order -/
242
243 /-- `s ≤ t` means that `s` is a sublist of `t` (up to permutation).
244 Equivalently, `s ≤ t` means that `count a s ≤ count a t` for all `a`. -/
245 protected def le (s t : multiset α) : Prop :=
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
246 quotient.lift_on₂ s t (<+~) $ λ v₁ v₂ w₁ w₂ p₁ p₂,
id └───────────────┘ ┴ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘
src └───────────────┘ ┴
typ └───────────────┘ ┴ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘
doc ┴
247 propext (p₂.subperm_left.trans p₁.subperm_right)
id └─────┘ └┘└───────────┘└────┘ └┘└────────────┘
src └─────┘ └───────────┘└────┘ └────────────┘
typ └─────┘ └┘└───────────┘└────┘ └┘└────────────┘
248
249 instance : partial_order (multiset α) :=
id └───────────┘ └──────┘ ┴
src └───────────┘ └──────┘
typ └───────────┘ └──────┘ ┴
doc └──────┘
250 { le := multiset.le,
id ┴ └─────────┘
src ┴ └─────────┘
typ ┴ └─────────┘
doc └─────────┘
251 le_refl := by rintros ⟨l⟩; exact subperm.refl _,
id └──────────┘
src └─────────┘ └────┘└──────────┘└┘
typ └─────────┘ └────┘└──────────┘└┘
doc └─────────┘ └────┘ └┘
txt └─────────┘ └────┘ └┘
par └─────────┘ └────┘ └┘
pid └──┘ ┴ └┘
st └────────────────────────────────┘
252 le_trans := by rintros ⟨l₁⟩ ⟨l₂⟩ ⟨l₃⟩; exact @subperm.trans _ _ _ _,
id └───────────┘
src └────────────────────┘ └────┘ └───────────┘└──────┘
typ └────────────────────┘ └────┘ └───────────┘└──────┘
doc └────────────────────┘ └────┘ └──────┘
txt └────────────────────┘ └────┘ └──────┘
par └────────────────────┘ └────┘ └──────┘
pid └─────────────┘ ┴ └──────┘
st └───────────────────────────────────────────────────┘
253 le_antisymm := by rintros ⟨l₁⟩ ⟨l₂⟩ h₁ h₂; exact quot.sound (subperm.antisymm h₁ h₂) }
id └────────┘ └──────────────┘ └┘ └┘
src └─────────────────────┘ └────┘└────────┘┴ └──────────────┘┴ ┴ └┘
typ └─────────────────────┘ └────┘└────────┘┴ └──────────────┘┴└┘┴└┘└┘
doc └─────────────────────┘ └────┘ ┴ ┴ ┴ └┘
txt └─────────────────────┘ └────┘ ┴ ┴ ┴ └┘
par └─────────────────────┘ └────┘ ┴ ┴ ┴ └┘
pid └──────────────┘ ┴ ┴ ┴ ┴ ┴┴
st └──────────────────────────────────────────────────────────────────┘
254
255 theorem subset_of_le {s t : multiset α} : s ≤ t → s ⊆ t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
256 quotient.induction_on₂ s t $ λ l₁ l₂, subset_of_subperm
id └────────────────────┘ ┴ ┴ └┘ └┘ └───────────────┘
src └────────────────────┘ └───────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └───────────────┘
257
258 theorem mem_of_le {s t : multiset α} {a : α} (h : s ≤ t) : a ∈ s → a ∈ t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
259 mem_of_subset (subset_of_le h)
id └───────────┘ └──────────┘ ┴
src └───────────┘ └──────────┘
typ └───────────┘ └──────────┘ ┴
260
261 @[simp] theorem coe_le {l₁ l₂ : list α} : (l₁ : multiset α) ≤ l₂ ↔ l₁ <+~ l₂ := iff.rfl
id └──┘ ┴ └┘ └──────┘ ┴ ┴ └┘ ┴ └┘ └─┘ └┘ └─────┘
src └──┘ └──────┘ ┴ ┴ └─┘ └─────┘
typ └──┘ ┴ └┘ └──────┘ ┴ ┴ └┘ ┴ └┘ └─┘ └┘ └─────┘
doc └──┘ └──────┘ └─┘
262
263 @[elab_as_eliminator] theorem le_induction_on {C : multiset α → multiset α → Prop}
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └────────────────┘ └──────┘ └──────┘
264 {s t : multiset α} (h : s ≤ t)
id └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴
doc └──────┘
265 (H : ∀ {l₁ l₂ : list α}, l₁ <+ l₂ → C l₁ l₂) : C s t :=
id └──┘ ┴ └┘ └┘ └┘ ┴ └┘ └┘ ┴ ┴ ┴
src └──┘ └┘
typ └──┘ ┴ └┘ └┘ └┘ ┴ └┘ └┘ ┴ ┴ ┴
266 quotient.induction_on₂ s t (λ l₁ l₂ ⟨l, p, s⟩,
id └────────────────────┘ ┴ ┴ └┘ └┘ ┴┴ ┴ ┴
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ ┴┴ ┴ ┴
267 (show ⟦l⟧ = ⟦l₁⟧, from quot.sound p) ▸ H s) h
id ┴ ┴ ┴ ┴└┘┴ └────────┘ ┴ ┴ ┴
src ┴ ┴ ┴ ┴ ┴ └────────┘ ┴
typ ┴ ┴ ┴ ┴└┘┴ └────────┘ ┴ ┴ ┴
268
269 theorem zero_le (s : multiset α) : 0 ≤ s :=
id └──────┘ ┴ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴ ┴
doc └──────┘
270 quot.induction_on s $ λ l, subperm_of_sublist $ nil_sublist l
id └───────────────┘ ┴ ┴ └────────────────┘ └─────────┘ ┴
src └───────────────┘ └────────────────┘ └─────────┘
typ └───────────────┘ ┴ ┴ └────────────────┘ └─────────┘ ┴
271
272 theorem le_zero {s : multiset α} : s ≤ 0 ↔ s = 0 :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
273 ⟨λ h, le_antisymm h (zero_le _), le_of_eq⟩
id ┴ └─────────┘ ┴ └─────┘ └──────┘
src └─────────┘ └─────┘ └──────┘
typ ┴ └─────────┘ ┴ └─────┘ └──────┘
274
275 theorem lt_cons_self (s : multiset α) (a : α) : s < a :: s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ └┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘
276 quot.induction_on s $ λ l,
id └───────────────┘ ┴ ┴
src └───────────────┘
typ └───────────────┘ ┴ ┴
277 suffices l <+~ a :: l ∧ (¬l ~ a :: l),
id ┴ └─┘ ┴ └┘ ┴ ┴ ┴┴ ┴ ┴ └┘ ┴
src └─┘ └┘ ┴ ┴ ┴ └┘
typ ┴ └─┘ ┴ └┘ ┴ ┴ ┴┴ ┴ ┴ └┘ ┴
doc └─┘ ┴
278 by simpa [lt_iff_le_and_ne],
id └──────────────┘
src └─────┘└──────────────┘┴
typ └─────┘└──────────────┘┴
doc └─────┘ ┴
txt └─────┘ ┴
par └─────┘ ┴
pid ┴┴ ┴
st └───────────────────────┘
279 ⟨subperm_of_sublist (sublist_cons _ _),
id └────────────────┘ └──────────┘
src └────────────────┘ └──────────┘
typ └────────────────┘ └──────────┘
280 λ p, ne_of_lt (lt_succ_self (length l)) (perm_length p)⟩
id ┴ └──────┘ └──────────┘ └────┘ ┴ └─────────┘ ┴
src └──────┘ └──────────┘ └────┘ └─────────┘
typ ┴ └──────┘ └──────────┘ └────┘ ┴ └─────────┘ ┴
281
282
283 theorem le_cons_self (s : multiset α) (a : α) : s ≤ a :: s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ └┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘
284 le_of_lt $ lt_cons_self _ _
id └──────┘ └──────────┘
src └──────┘ └──────────┘
typ └──────┘ └──────────┘
285
286 theorem cons_le_cons_iff (a : α) {s t : multiset α} : a :: s ≤ a :: t ↔ s ≤ t :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └┘ ┴ └┘ ┴ ┴
typ ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └┘ └┘
287 quotient.induction_on₂ s t $ λ l₁ l₂, subperm_cons a
id └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘ ┴
src └────────────────────┘ └──────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘ ┴
288
289 theorem cons_le_cons (a : α) {s t : multiset α} : s ≤ t → a :: s ≤ a :: t :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ └┘ ┴ └┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘ └┘
290 (cons_le_cons_iff a).2
id └──────────────┘ ┴ ┴
src └──────────────┘ ┴
typ └──────────────┘ ┴ ┴
291
292 theorem le_cons_of_not_mem {a : α} {s t : multiset α} (m : a ∉ s) : s ≤ a :: t ↔ s ≤ t :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ └┘ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └┘
293 begin
st └─────
294 refine ⟨_, λ h, le_trans h $ le_cons_self _ _⟩,
id └──────┘ └──────────┘
src └─────┘ └─┘ └──┘└──────┘┴ ┴ ┴└──────────┘└───┘
typ └─────┘ └─┘ └──┘└──────┘┴ ┴ ┴└──────────┘└───┘
doc └─────┘ └─┘ └──┘ ┴ ┴ ┴ └───┘
txt └─────┘ └─┘ └──┘ ┴ ┴ ┴ └───┘
par └─────┘ └─┘ └──┘ ┴ ┴ ┴ └───┘
pid ┴ └─┘ └──┘ ┴ ┴ ┴ └───┘
st ───────────────────────────────────────────────┘└─
295 suffices : ∀ {t'} (_ : s ≤ t') (_ : a ∈ t'), a :: s ≤ t',
id ┴ ┴ ┴ └┘ ┴
src └─────────┘ └─────────┘ ┴┴┴ └─────┘ ┴┴┴ ┴ ┴ ┴└┘┴ ┴ ┴
typ └─────────┘ └─────────┘ ┴┴┴ └─────┘ ┴┴┴ ┴ ┴┴┴└┘┴┴┴ ┴
doc └─────────┘ └─────────┘ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴└┘┴ ┴ ┴
txt └─────────┘ └─────────┘ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
par └─────────┘ └─────────┘ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
pid └───────┘└┘ └─────────┘ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
st ─────────────────────────────────────────────────────────┘└─
296 { exact λ h, (cons_le_cons_iff a).1 (this h (mem_cons_self _ _)) },
id └──────────────┘ ┴ └──┘ └───────────┘
src └────┘ └──┘ └──────────────┘┴ └──┘ ┴ ┴ └───────────┘└─────┘
typ └────┘ └──┘ └──────────────┘┴┴└──┘ └──┘┴ ┴ └───────────┘└─────┘
doc └────┘ └──┘ ┴ └──┘ ┴ ┴ └─────┘
txt └────┘ └──┘ ┴ └──┘ ┴ ┴ └─────┘
par └────┘ └──┘ ┴ └──┘ ┴ ┴ └─────┘
pid ┴ └──┘ ┴ └──┘ ┴ ┴ └────┘┴
st ───┘└─────────────────────────────────────────────────────────────┘└┘└
297 introv h, revert m, refine le_induction_on h _,
id └─────────────┘ ┴
src └──────┘ └──────┘ └─────┘└─────────────┘┴ └┘
typ └──────┘ └──────┘ └─────┘└─────────────┘┴┴└┘
doc └──────┘ └──────┘ └─────┘ ┴ └┘
txt └──────┘ └──────┘ └─────┘ ┴ └┘
par └──────┘ └──────┘ └─────┘ ┴ └┘
pid └┘ └┘ ┴ ┴ └┘
st ─────────┘└────────┘└──────────────────────────┘└─
298 introv s m₁ m₂,
src └────────────┘
typ └────────────┘
doc └────────────┘
txt └────────────┘
par └────────────┘
pid └──────┘
st ───────────────┘└─
299 rcases mem_split m₂ with ⟨r₁, r₂, rfl⟩,
id └───────┘ └┘
src └─────┘└───────┘┴ └─────────────────┘
typ └─────┘└───────┘┴└┘└─────────────────┘
doc └─────┘ ┴ └─────────────────┘
txt └─────┘ ┴ └─────────────────┘
par └─────┘ ┴ └─────────────────┘
pid ┴ ┴ └─────────────────┘
st ───────────────────────────────────────┘└─
300 exact perm_middle.subperm_left.2 ((subperm_cons _).2 $ subperm_of_sublist $
id └──────────────────────┘ └──────────┘ └────────────────┘
src └────┘└──────────────────────┘└─┘ └──────────┘└────┘ ┴└────────────────┘┴ └
typ └────┘└──────────────────────┘└─┘ └──────────┘└────┘ ┴└────────────────┘┴ └
doc └────┘ └─┘ └────┘ ┴ ┴ └
txt └────┘ └─┘ └────┘ ┴ ┴ └
par └────┘ └─┘ └────┘ ┴ ┴ └
pid ┴ └─┘ └────┘ ┴ ┴ └
st ──────────────────────────────────────────────────────────────────────────────
301 (sublist_or_mem_of_sublist s).resolve_right m₁)
id └───────────────────────┘ ┴ └┘
src ───┘ └───────────────────────┘┴ └──────────────┘ └┘
typ ───┘ └───────────────────────┘┴┴└──────────────┘└┘└┘
doc ───┘ ┴ └──────────────┘ └┘
txt ───┘ ┴ └──────────────┘ └┘
par ───┘ ┴ └──────────────┘ └┘
pid ───┘ ┴ └──────────────┘ ┴┴
st ───────────────────────────────────────────────────┘
302 end
st └─┘
303
304 /- cardinality -/
305
306 /-- The cardinality of a multiset is the sum of the multiplicities
307 of all its elements, or simply the length of the underlying list. -/
308 def card (s : multiset α) : ℕ :=
id └──────┘ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴
doc └──────┘
309 quot.lift_on s length $ λ l₁ l₂, perm_length
id └──────────┘ ┴ └────┘ └┘ └┘ └─────────┘
src └──────────┘ └────┘ └─────────┘
typ └──────────┘ ┴ └────┘ └┘ └┘ └─────────┘
310
311 @[simp] theorem coe_card (l : list α) : card (l : multiset α) = length l := rfl
id └──┘ ┴ └──┘ ┴ └──────┘ ┴ ┴ └────┘ ┴ └─┘
src └──┘ └──┘ └──────┘ ┴ └────┘ └─┘
typ └──┘ ┴ └──┘ ┴ └──────┘ ┴ ┴ └────┘ ┴ └─┘
doc └──┘ └──┘ └──────┘
312
313 @[simp] theorem card_zero : @card α 0 = 0 := rfl
id └──┘ ┴ ┴ └─┘
src └──┘ ┴ └─┘
typ └──┘ ┴ ┴ └─┘
doc └──┘ └──┘
314
315 @[simp] theorem card_cons (a : α) (s : multiset α) : card (a :: s) = card s + 1 :=
id ┴ └──────┘ ┴ └──┘ ┴ └┘ ┴ ┴ └──┘ ┴ ┴
src └──────┘ └──┘ └┘ ┴ └──┘ ┴
typ ┴ └──────┘ ┴ └──┘ ┴ └┘ ┴ ┴ └──┘ ┴ ┴
doc └──┘ └──────┘ └──┘ └┘ └──┘
316 quot.induction_on s $ λ l, rfl
id └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ └───────────────┘ ┴ ┴ └─┘
317
318 @[simp] theorem card_singleton (a : α) : card (a::0) = 1 := by simp
id ┴ └──┘ ┴└┘ ┴
src └──┘ └┘ ┴ └────
typ ┴ └──┘ ┴└┘ ┴ └────
doc └──┘ └──┘ └┘ └────
txt └────
par └────
pid └
st └─────
319
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
320 theorem card_le_of_le {s t : multiset α} (h : s ≤ t) : card s ≤ card t :=
id └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
src └──────┘ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
doc └──────┘ └──┘ └──┘
321 le_induction_on h $ λ l₁ l₂, length_le_of_sublist
id └─────────────┘ ┴ └┘ └┘ └──────────────────┘
src └─────────────┘ └──────────────────┘
typ └─────────────┘ ┴ └┘ └┘ └──────────────────┘
322
323 theorem eq_of_le_of_card_le {s t : multiset α} (h : s ≤ t) : card t ≤ card s → s = t :=
id └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──┘ ┴ └──┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
doc └──────┘ └──┘ └──┘
324 le_induction_on h $ λ l₁ l₂ s h₂, congr_arg coe $ eq_of_sublist_of_length_le s h₂
id └─────────────┘ ┴ └┘ └┘ ┴ └┘ └───────┘ └─┘ └────────────────────────┘ ┴ └┘
src └─────────────┘ └───────┘ └─┘ └────────────────────────┘
typ └─────────────┘ ┴ └┘ └┘ ┴ └┘ └───────┘ └─┘ └────────────────────────┘ ┴ └┘
325
326 theorem card_lt_of_lt {s t : multiset α} (h : s < t) : card s < card t :=
id └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
src └──────┘ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
doc └──────┘ └──┘ └──┘
327 lt_of_not_ge $ λ h₂, ne_of_lt h $ eq_of_le_of_card_le (le_of_lt h) h₂
id └──────────┘ └┘ └──────┘ ┴ └─────────────────┘ └──────┘ ┴ └┘
src └──────────┘ └──────┘ └─────────────────┘ └──────┘
typ └──────────┘ └┘ └──────┘ ┴ └─────────────────┘ └──────┘ ┴ └┘
328
329 theorem lt_iff_cons_le {s t : multiset α} : s < t ↔ ∃ a, a :: s ≤ t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ └┘ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ └┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ └┘ ┴ ┴ ┴
doc └──────┘ └┘
330 ⟨quotient.induction_on₂ s t $ λ l₁ l₂ h,
id └────────────────────┘ ┴ ┴ └┘ └┘ ┴
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ ┴
331 subperm.exists_of_length_lt (le_of_lt h) (card_lt_of_lt h),
id └─────────────────────────┘ └──────┘ ┴ └───────────┘ ┴
src └─────────────────────────┘ └──────┘ └───────────┘
typ └─────────────────────────┘ └──────┘ ┴ └───────────┘ ┴
332 λ ⟨a, h⟩, lt_of_lt_of_le (lt_cons_self _ _) h⟩
id ┴ ┴ └────────────┘ └──────────┘
src └────────────┘ └──────────┘
typ ┴ ┴ └────────────┘ └──────────┘
333
334 @[simp] theorem card_eq_zero {s : multiset α} : card s = 0 ↔ s = 0 :=
id └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──┘ ┴ ┴ ┴
typ └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──┘
335 ⟨λ h, (eq_of_le_of_card_le (zero_le _) (le_of_eq h)).symm, λ e, by simp [e]⟩
id ┴ └─────────────────┘ └─────┘ └──────┘ ┴ └──┘ ┴ ┴
src └─────────────────┘ └─────┘ └──────┘ └──┘ └────┘ ┴
typ ┴ └─────────────────┘ └─────┘ └──────┘ ┴ └──┘ ┴ └────┘┴┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └───────┘
336
337 theorem card_pos {s : multiset α} : 0 < card s ↔ s ≠ 0 :=
id └──────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──┘ ┴ ┴
typ └──────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
doc └──────┘ └──┘
338 pos_iff_ne_zero.trans $ not_congr card_eq_zero
id └─────────────┘└────┘ └───────┘ └──────────┘
src └─────────────┘└────┘ └───────┘ └──────────┘
typ └─────────────┘└────┘ └───────┘ └──────────┘
339
340 theorem card_pos_iff_exists_mem {s : multiset α} : 0 < card s ↔ ∃ a, a ∈ s :=
id └──────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
src └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
doc └──────┘ └──┘
341 quot.induction_on s $ λ l, length_pos_iff_exists_mem
id └───────────────┘ ┴ ┴ └───────────────────────┘
src └───────────────┘ └───────────────────────┘
typ └───────────────┘ ┴ ┴ └───────────────────────┘
342
343 @[elab_as_eliminator] def strong_induction_on {p : multiset α → Sort*} :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └────────────────┘ └──────┘
344 ∀ (s : multiset α), (∀ s, (∀t < s, p t) → p s) → p s
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
345 | s := λ ih, ih s $ λ t h,
id ┴ └┘ └┘ ┴ ┴
typ ┴ └┘ └┘ ┴ ┴
346 have card t < card s, from card_lt_of_lt h,
id └──┘ ┴ ┴ └──┘ └───────────┘ ┴
src └──┘ ┴ └──┘ └───────────┘
typ └──┘ ┴ ┴ └──┘ └───────────┘ ┴
doc └──┘ └──┘
347 strong_induction_on t ih
id └─────────────────┘ ┴ └┘
typ └─────────────────┘ ┴ └┘
348 using_well_founded {rel_tac := λ _ _, `[exact ⟨_, measure_wf card⟩]}
id ┴ ┴
src └────┘ └─┘ ┴ ┴
typ ┴ ┴ └────┘ └─┘ ┴ ┴
doc └────┘ └─┘ ┴ ┴
txt └────┘ └─┘ ┴ ┴
par └────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴
349
350 theorem strong_induction_eq {p : multiset α → Sort*}
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
351 (s : multiset α) (H) : @strong_induction_on _ p s H =
id └──────┘ ┴ └─────────────────┘ ┴ ┴ ┴ ┴
src └──────┘ └─────────────────┘ ┴
typ └──────┘ ┴ └─────────────────┘ ┴ ┴ ┴ ┴
doc └──────┘
352 H s (λ t h, @strong_induction_on _ p t H) :=
id ┴ ┴ ┴ ┴ └─────────────────┘ ┴ ┴ ┴
src └─────────────────┘
typ ┴ ┴ ┴ ┴ └─────────────────┘ ┴ ┴ ┴
353 by rw [strong_induction_on]
id └─────────────────┘
src └──┘└─────────────────┘└─
typ └──┘└─────────────────┘└─
doc └──┘ └─
txt └──┘ └─
par └──┘ └─
pid └┘ ┴└
st └──────────────────────┘┴└
354
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
355 @[elab_as_eliminator] lemma case_strong_induction_on {p : multiset α → Prop}
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └────────────────┘ └──────┘
356 (s : multiset α) (h₀ : p 0) (h₁ : ∀ a s, (∀t ≤ s, p t) → p (a :: s)) : p s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
src └──────┘ ┴ └┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
doc └──────┘ └┘
357 multiset.strong_induction_on s $ assume s,
id └──────────────────────────┘ ┴ ┴
src └──────────────────────────┘
typ └──────────────────────────┘ ┴ ┴
358 multiset.induction_on s (λ _, h₀) $ λ a s _ ih, h₁ _ _ $
id └───────────────────┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ └┘
src └───────────────────┘
typ └───────────────────┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ └┘
359 λ t h, ih _ $ lt_of_le_of_lt h $ lt_cons_self _ _
id ┴ ┴ └┘ └────────────┘ ┴ └──────────┘
src └────────────┘ └──────────┘
typ ┴ ┴ └┘ └────────────┘ ┴ └──────────┘
360
361 /- singleton -/
362 @[simp] theorem singleton_eq_singleton (a : α) : singleton a = a::0 := rfl
id ┴ └───────┘ ┴ ┴ ┴└┘ └─┘
src └───────┘ ┴ └┘ └─┘
typ ┴ └───────┘ ┴ ┴ ┴└┘ └─┘
doc └──┘ └┘
363
364 @[simp] theorem mem_singleton {a b : α} : b ∈ a::0 ↔ b = a := by simp
id ┴ ┴ ┴ ┴└┘ ┴ ┴ ┴ ┴
src ┴ └┘ ┴ ┴ └────
typ ┴ ┴ ┴ ┴└┘ ┴ ┴ ┴ ┴ └────
doc └──┘ └┘ └────
txt └────
par └────
pid └
st └─────
365
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
366 theorem mem_singleton_self (a : α) : a ∈ (a::0 : multiset α) := mem_cons_self _ _
id ┴ ┴ ┴ ┴└┘ └──────┘ ┴ └───────────┘
src ┴ └┘ └──────┘ └───────────┘
typ ┴ ┴ ┴ ┴└┘ └──────┘ ┴ └───────────┘
doc └┘ └──────┘
367
368 theorem singleton_inj {a b : α} : a::0 = b::0 ↔ a = b := cons_inj_left _
id ┴ ┴└┘ ┴ ┴└┘ ┴ ┴ ┴ ┴ └───────────┘
src └┘ ┴ └┘ ┴ ┴ └───────────┘
typ ┴ ┴└┘ ┴ ┴└┘ ┴ ┴ ┴ ┴ └───────────┘
doc └┘ └┘
369
370 @[simp] theorem singleton_ne_zero (a : α) : a::0 ≠ 0 :=
id ┴ ┴└┘ ┴
src └┘ ┴
typ ┴ ┴└┘ ┴
doc └──┘ └┘
371 ne_of_gt (lt_cons_self _ _)
id └──────┘ └──────────┘
src └──────┘ └──────────┘
typ └──────┘ └──────────┘
372
373 @[simp] theorem singleton_le {a : α} {s : multiset α} : a::0 ≤ s ↔ a ∈ s :=
id ┴ └──────┘ ┴ ┴└┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └┘ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴└┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └┘
374 ⟨λ h, mem_of_le h (mem_singleton_self _),
id ┴ └───────┘ ┴ └────────────────┘
src └───────┘ └────────────────┘
typ ┴ └───────┘ ┴ └────────────────┘
375 λ h, let ⟨t, e⟩ := exists_cons_of_mem h in e.symm ▸ cons_le_cons _ (zero_le _)⟩
id ┴ └─┘ ┴ └────────────────┘ ┴ └───┘ ┴ └──────────┘ └─────┘
src └────────────────┘ └───┘ ┴ └──────────┘ └─────┘
typ ┴ └─┘ ┴ └────────────────┘ ┴ └───┘ ┴ └──────────┘ └─────┘
376
377 theorem card_eq_one {s : multiset α} : card s = 1 ↔ ∃ a, s = a::0 :=
id └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴└┘
src └──────┘ └──┘ ┴ ┴ ┴ ┴ ┴ └┘
typ └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴└┘
doc └──────┘ └──┘ └┘
378 ⟨quot.induction_on s $ λ l h,
id └───────────────┘ ┴ ┴ ┴
src └───────────────┘
typ └───────────────┘ ┴ ┴ ┴
379 (list.length_eq_one.1 h).imp $ λ a, congr_arg coe,
id └────────────────┘┴ ┴ └─┘ ┴ └───────┘ └─┘
src └────────────────┘┴ └─┘ └───────┘ └─┘
typ └────────────────┘┴ ┴ └─┘ ┴ └───────┘ └─┘
380 λ ⟨a, e⟩, e.symm ▸ rfl⟩
id ┴ ┴ └───┘ ┴ └─┘
src └───┘ ┴ └─┘
typ ┴ ┴ └───┘ ┴ └─┘
381
382 /- add -/
383
384 /-- The sum of two multisets is the lift of the list append operation.
385 This adds the multiplicities of each element,
386 i.e. `count a (s + t) = count a s + count a t`. -/
387 protected def add (s₁ s₂ : multiset α) : multiset α :=
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
388 quotient.lift_on₂ s₁ s₂ (λ l₁ l₂, ((l₁ ++ l₂ : list α) : multiset α)) $
id └───────────────┘ └┘ └┘ └┘ └┘ └┘ └┘ └┘ └──┘ ┴ └──────┘ ┴
src └───────────────┘ └┘ └──┘ └──────┘
typ └───────────────┘ └┘ └┘ └┘ └┘ └┘ └┘ └┘ └──┘ ┴ └──────┘ ┴
doc └──────┘
389 λ v₁ v₂ w₁ w₂ p₁ p₂, quot.sound $ perm_app p₁ p₂
id └┘ └┘ └┘ └┘ └┘ └┘ └────────┘ └──────┘ └┘ └┘
src └────────┘ └──────┘
typ └┘ └┘ └┘ └┘ └┘ └┘ └────────┘ └──────┘ └┘ └┘
390
391 instance : has_add (multiset α) := ⟨multiset.add⟩
id └─────┘ └──────┘ ┴ └──────────┘
src └─────┘ └──────┘ └──────────┘
typ └─────┘ └──────┘ ┴ └──────────┘
doc └──────┘ └──────────┘
392
393 @[simp] theorem coe_add (s t : list α) : (s + t : multiset α) = (s ++ t : list α) := rfl
id └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └┘ ┴ └──┘ ┴ └─┘
src └──┘ ┴ └──────┘ ┴ └┘ └──┘ └─┘
typ └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └┘ ┴ └──┘ ┴ └─┘
doc └──┘ └──────┘
394
395 protected theorem add_comm (s t : multiset α) : s + t = t + s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
396 quotient.induction_on₂ s t $ λ l₁ l₂, quot.sound perm_app_comm
id └────────────────────┘ ┴ ┴ └┘ └┘ └────────┘ └───────────┘
src └────────────────────┘ └────────┘ └───────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └────────┘ └───────────┘
397
398 protected theorem zero_add (s : multiset α) : 0 + s = s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘
399 quot.induction_on s $ λ l, rfl
id └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ └───────────────┘ ┴ ┴ └─┘
400
401 theorem singleton_add (a : α) (s : multiset α) : ↑[a] + s = a::s := rfl
id ┴ └──────┘ ┴ ┴┴┴┴ ┴ ┴ ┴ ┴└┘┴ └─┘
src └──────┘ ┴┴ ┴ ┴ ┴ └┘ └─┘
typ ┴ └──────┘ ┴ ┴┴┴┴ ┴ ┴ ┴ ┴└┘┴ └─┘
doc └──────┘ └┘
402
403 protected theorem add_le_add_left (s) {t u : multiset α} : s + t ≤ s + u ↔ t ≤ u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
404 quotient.induction_on₃ s t u $ λ l₁ l₂ l₃, subperm_app_left _
id └────────────────────┘ ┴ ┴ ┴ └┘ └┘ └┘ └──────────────┘
src └────────────────────┘ └──────────────┘
typ └────────────────────┘ ┴ ┴ ┴ └┘ └┘ └┘ └──────────────┘
405
406 protected theorem add_left_cancel (s) {t u : multiset α} (h : s + t = s + u) : t = u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
407 le_antisymm ((multiset.add_le_add_left _).1 (le_of_eq h))
id └─────────┘ └──────────────────────┘ ┴ └──────┘ ┴
src └─────────┘ └──────────────────────┘ ┴ └──────┘
typ └─────────┘ └──────────────────────┘ ┴ └──────┘ ┴
408 ((multiset.add_le_add_left _).1 (le_of_eq h.symm))
id └──────────────────────┘ ┴ └──────┘ ┴└───┘
src └──────────────────────┘ ┴ └──────┘ └───┘
typ └──────────────────────┘ ┴ └──────┘ ┴└───┘
409
410 instance : ordered_cancel_comm_monoid (multiset α) :=
id └────────────────────────┘ └──────┘ ┴
src └────────────────────────┘ └──────┘
typ └────────────────────────┘ └──────┘ ┴
doc └──────┘
411 { zero := 0,
412 add := (+),
id ┴
src ┴
typ ┴
413 add_comm := multiset.add_comm,
id └───────────────┘
src └───────────────┘
typ └───────────────┘
414 add_assoc := λ s₁ s₂ s₃, quotient.induction_on₃ s₁ s₂ s₃ $ λ l₁ l₂ l₃,
id └┘ └┘ └┘ └────────────────────┘ └┘ └┘ └┘ └┘ └┘ └┘
src └────────────────────┘
typ └┘ └┘ └┘ └────────────────────┘ └┘ └┘ └┘ └┘ └┘ └┘
415 congr_arg coe $ append_assoc l₁ l₂ l₃,
id └───────┘ └─┘ └──────────┘ └┘ └┘ └┘
src └───────┘ └─┘ └──────────┘
typ └───────┘ └─┘ └──────────┘ └┘ └┘ └┘
416 zero_add := multiset.zero_add,
id └───────────────┘
src └───────────────┘
typ └───────────────┘
417 add_zero := λ s, by rw [multiset.add_comm, multiset.zero_add],
id ┴ └───────────────┘ └───────────────┘
src └──┘└───────────────┘└┘└───────────────┘┴
typ ┴ └──┘└───────────────┘└┘└───────────────┘┴
doc └──┘ └┘ ┴
txt └──┘ └┘ ┴
par └──┘ └┘ ┴
pid └┘ └┘ ┴
st └────────────────────┘└─────────────────┘┴
418 add_left_cancel := multiset.add_left_cancel,
id └──────────────────────┘
src └──────────────────────┘
typ └──────────────────────┘
419 add_right_cancel := λ s₁ s₂ s₃ h, multiset.add_left_cancel s₂ $
id └┘ └┘ └┘ ┴ └──────────────────────┘ └┘
src └──────────────────────┘
typ └┘ └┘ └┘ ┴ └──────────────────────┘ └┘
420 by simpa [multiset.add_comm] using h,
id └───────────────┘ ┴
src └─────┘└───────────────┘└──────┘
typ └─────┘└───────────────┘└──────┘┴
doc └─────┘ └──────┘
txt └─────┘ └──────┘
par └─────┘ └──────┘
pid ┴┴ ┴┴└────┘
st └────────────────────────────────┘
421 add_le_add_left := λ s₁ s₂ h s₃, (multiset.add_le_add_left _).2 h,
id └┘ └┘ ┴ └┘ └──────────────────────┘ ┴ ┴
src └──────────────────────┘ ┴
typ └┘ └┘ ┴ └┘ └──────────────────────┘ ┴ ┴
422 le_of_add_le_add_left := λ s₁ s₂ s₃, (multiset.add_le_add_left _).1,
id └┘ └┘ └┘ └──────────────────────┘ ┴
src └──────────────────────┘ ┴
typ └┘ └┘ └┘ └──────────────────────┘ ┴
423 ..@multiset.partial_order α }
id └────────────────────┘ ┴
src └────────────────────┘
typ └────────────────────┘ ┴
424
425 @[simp] theorem cons_add (a : α) (s t : multiset α) : a :: s + t = a :: (s + t) :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
src └──────┘ └┘ ┴ ┴ └┘ ┴
typ ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
doc └──┘ └──────┘ └┘ └┘
426 by rw [← singleton_add, ← singleton_add, add_assoc]
id └───────────┘ └───────────┘ └───────┘
src └────┘└───────────┘└──┘└───────────┘└┘└───────┘└─
typ └────┘└───────────┘└──┘└───────────┘└┘└───────┘└─
doc └────┘ └──┘ └┘ └─
txt └────┘ └──┘ └┘ └─
par └────┘ └──┘ └┘ └─
pid └──┘ └──┘ └┘ ┴└
st └──────────────────┘└───────────────┘└─────────┘┴└
427
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
428 @[simp] theorem add_cons (a : α) (s t : multiset α) : s + a :: t = a :: (s + t) :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴
src └──────┘ ┴ └┘ ┴ └┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴
doc └──┘ └──────┘ └┘ └┘
429 by rw [add_comm, cons_add, add_comm]
id └──────┘ └──────┘ └──────┘
src └──┘└──────┘└┘└──────┘└┘└──────┘└─
typ └──┘└──────┘└┘└──────┘└┘└──────┘└─
doc └──┘ └┘ └┘ └─
txt └──┘ └┘ └┘ └─
par └──┘ └┘ └┘ └─
pid └┘ └┘ └┘ ┴└
st └───────────┘└────────┘└────────┘┴└
430
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
431 theorem le_add_right (s t : multiset α) : s ≤ s + t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
432 by simpa using add_le_add_left (zero_le t) s
id └─────────────┘ └─────┘ ┴ ┴
src └──────────┘└─────────────┘┴ └─────┘┴ └┘ └
typ └──────────┘└─────────────┘┴ └─────┘┴┴└┘┴└
doc └──────────┘ ┴ ┴ └┘ └
txt └──────────┘ ┴ ┴ └┘ └
par └──────────┘ ┴ ┴ └┘ └
pid ┴└────┘ ┴ ┴ └┘ └
st └──────────────────────────────────────────
433
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
434 theorem le_add_left (s t : multiset α) : s ≤ t + s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
435 by simpa using add_le_add_right (zero_le t) s
id └──────────────┘ └─────┘ ┴ ┴
src └──────────┘└──────────────┘┴ └─────┘┴ └┘ └
typ └──────────┘└──────────────┘┴ └─────┘┴┴└┘┴└
doc └──────────┘ ┴ ┴ └┘ └
txt └──────────┘ ┴ ┴ └┘ └
par └──────────┘ ┴ ┴ └┘ └
pid ┴└────┘ ┴ ┴ └┘ └
st └───────────────────────────────────────────
436
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
437 @[simp] theorem card_add (s t : multiset α) : card (s + t) = card s + card t :=
id └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
src └──────┘ └──┘ ┴ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
doc └──┘ └──────┘ └──┘ └──┘ └──┘
438 quotient.induction_on₂ s t length_append
id └────────────────────┘ ┴ ┴ └───────────┘
src └────────────────────┘ └───────────┘
typ └────────────────────┘ ┴ ┴ └───────────┘
439
440 lemma card_smul (s : multiset α) (n : ℕ) :
id └──────┘ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴
doc └──────┘
441 (n • s).card = n * s.card :=
id ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴└───┘
src ┴ └──┘ ┴ ┴ └───┘
typ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴└───┘
doc └──┘ └───┘
442 by induction n; simp [succ_smul, *, nat.succ_mul]
id ┴ └───────┘ └──────────┘
src └────────┘ └────┘└───────┘└───┘└──────────┘└─
typ └────────┘┴ └────┘└───────┘└───┘└──────────┘└─
doc └────────┘ └────┘ └───┘ └─
txt └────────┘ └────┘ └───┘ └─
par └────────┘ └────┘ └───┘ └─
pid ┴ ┴┴ └───┘ ┴└
st └───────────────────────────────────────────────
443
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
444 @[simp] theorem mem_add {a : α} {s t : multiset α} : a ∈ s + t ↔ a ∈ s ∨ a ∈ t :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
445 quotient.induction_on₂ s t $ λ l₁ l₂, mem_append
id └────────────────────┘ ┴ ┴ └┘ └┘ └────────┘
src └────────────────────┘ └────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └────────┘
446
447 theorem le_iff_exists_add {s t : multiset α} : s ≤ t ↔ ∃ u, t = s + u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
448 ⟨λ h, le_induction_on h $ λ l₁ l₂ s,
id ┴ └─────────────┘ ┴ └┘ └┘ ┴
src └─────────────┘
typ ┴ └─────────────┘ ┴ └┘ └┘ ┴
449 let ⟨l, p⟩ := exists_perm_append_of_sublist s in ⟨l, quot.sound p⟩,
id └─┘ ┴ ┴ └───────────────────────────┘ ┴ └────────┘
src └───────────────────────────┘ └────────┘
typ └─┘ ┴ ┴ └───────────────────────────┘ ┴ └────────┘
450 λ⟨u, e⟩, e.symm ▸ le_add_right s u⟩
id ┴┴ ┴ └───┘ ┴ └──────────┘ ┴
src └───┘ ┴ └──────────┘
typ ┴┴ ┴ └───┘ ┴ └──────────┘ ┴
451
452 instance : canonically_ordered_monoid (multiset α) :=
id └────────────────────────┘ └──────┘ ┴
src └────────────────────────┘ └──────┘
typ └────────────────────────┘ └──────┘ ┴
doc └────────────────────────┘ └──────┘
453 { lt_of_add_lt_add_left := @lt_of_add_lt_add_left _ _,
id └───────────────────┘
src └───────────────────┘
typ └───────────────────┘
454 le_iff_exists_add := @le_iff_exists_add _,
id └───────────────┘
src └───────────────┘
typ └───────────────┘
455 bot := 0,
456 bot_le := multiset.zero_le,
id └──────────────┘
src └──────────────┘
typ └──────────────┘
457 ..multiset.ordered_cancel_comm_monoid }
id └─────────────────────────────────┘
src └─────────────────────────────────┘
typ └─────────────────────────────────┘
458
459 /- repeat -/
460
461 /-- `repeat a n` is the multiset containing only `a` with multiplicity `n`. -/
462 def repeat (a : α) (n : ℕ) : multiset α := repeat a n
id ┴ ┴ └──────┘ ┴ └────┘ ┴ ┴
src ┴ └──────┘ └────┘
typ ┴ ┴ └──────┘ ┴ └────┘ ┴ ┴
doc └──────┘
463
464 @[simp] lemma repeat_zero (a : α) : repeat a 0 = 0 := rfl
id ┴ └────┘ ┴ ┴ └─┘
src └────┘ ┴ └─┘
typ ┴ └────┘ ┴ ┴ └─┘
doc └──┘ └────┘
465
466 @[simp] lemma repeat_succ (a : α) (n) : repeat a (n+1) = a :: repeat a n := by simp [repeat]
id ┴ └────┘ ┴ ┴┴ ┴ ┴ └┘ └────┘ ┴ ┴ └────┘
src └────┘ ┴ ┴ └┘ └────┘ └────┘└────┘└─
typ ┴ └────┘ ┴ ┴┴ ┴ ┴ └┘ └────┘ ┴ ┴ └────┘└────┘└─
doc └──┘ └────┘ └┘ └────┘ └────┘└────┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └──────────────
467
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
468 @[simp] lemma repeat_one (a : α) : repeat a 1 = a :: 0 := by simp
id ┴ └────┘ ┴ ┴ ┴ └┘
src └────┘ ┴ └┘ └────
typ ┴ └────┘ ┴ ┴ ┴ └┘ └────
doc └──┘ └────┘ └┘ └────
txt └────
par └────
pid └
st └─────
469
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
470 @[simp] lemma card_repeat : ∀ (a : α) n, card (repeat a n) = n := length_repeat
id ┴ ┴ └──┘ └────┘ ┴ ┴ ┴ ┴ └───────────┘
src └──┘ └────┘ ┴ └───────────┘
typ ┴ ┴ └──┘ └────┘ ┴ ┴ ┴ ┴ └───────────┘
doc └──┘ └──┘ └────┘
471
472 theorem eq_of_mem_repeat {a b : α} {n} : b ∈ repeat a n → b = a := eq_of_mem_repeat
id ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └──────────────┘
src ┴ └────┘ ┴ └──────────────┘
typ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └──────────────┘
doc └────┘
473
474 theorem eq_repeat' {a : α} {s : multiset α} : s = repeat a s.card ↔ ∀ b ∈ s, b = a :=
id ┴ └──────┘ ┴ ┴ ┴ └────┘ ┴ ┴└───┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └────┘ └───┘ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ └────┘ ┴ ┴└───┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └────┘ └───┘
475 quot.induction_on s $ λ l, iff.trans ⟨λ h,
id └───────────────┘ ┴ ┴ └───────┘ ┴
src └───────────────┘ └───────┘
typ └───────────────┘ ┴ ┴ └───────┘ ┴
476 (perm_repeat.1 $ (quotient.exact h).symm).symm, congr_arg coe⟩ eq_repeat'
id └─────────┘┴ └────────────┘ ┴ └──┘ └──┘ └───────┘ └─┘ └────────┘
src └─────────┘┴ └────────────┘ └──┘ └──┘ └───────┘ └─┘ └────────┘
typ └─────────┘┴ └────────────┘ ┴ └──┘ └──┘ └───────┘ └─┘ └────────┘
477
478 theorem eq_repeat_of_mem {a : α} {s : multiset α} : (∀ b ∈ s, b = a) → s = repeat a s.card :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴└───┘
src └──────┘ ┴ ┴ └────┘ └───┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴└───┘
doc └──────┘ └────┘ └───┘
479 eq_repeat'.2
id └────────┘┴
src └────────┘┴
typ └────────┘┴
480
481 theorem eq_repeat {a : α} {n} {s : multiset α} : s = repeat a n ↔ card s = n ∧ ∀ b ∈ s, b = a :=
id ┴ └──────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └────┘ ┴ └──┘ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └────┘ └──┘
482 ⟨λ h, h.symm ▸ ⟨card_repeat _ _, λ b, eq_of_mem_repeat⟩,
id ┴ ┴└───┘ ┴ └─────────┘ ┴ └──────────────┘
src └───┘ ┴ └─────────┘ └──────────────┘
typ ┴ ┴└───┘ ┴ └─────────┘ ┴ └──────────────┘
483 λ ⟨e, al⟩, e ▸ eq_repeat_of_mem al⟩
id ┴┴ └┘ ┴ └──────────────┘
src ┴ └──────────────┘
typ ┴┴ └┘ ┴ └──────────────┘
484
485 theorem repeat_subset_singleton : ∀ (a : α) n, repeat a n ⊆ a::0 := repeat_subset_singleton
id ┴ ┴ └────┘ ┴ ┴ ┴ ┴└┘ └─────────────────────┘
src └────┘ ┴ └┘ └─────────────────────┘
typ ┴ ┴ └────┘ ┴ ┴ ┴ ┴└┘ └─────────────────────┘
doc └────┘ └┘
486
487 theorem repeat_le_coe {a : α} {n} {l : list α} : repeat a n ≤ l ↔ list.repeat a n <+ l :=
id ┴ └──┘ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─────────┘ ┴ ┴ └┘ ┴
src └──┘ └────┘ ┴ ┴ └─────────┘ └┘
typ ┴ └──┘ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─────────┘ ┴ ┴ └┘ ┴
doc └────┘
488 ⟨λ ⟨l', p, s⟩, (perm_repeat.1 p.symm).symm ▸ s, subperm_of_sublist⟩
id ┴ ┴ ┴ └─────────┘┴ └───┘ └──┘ ┴ └────────────────┘
src └─────────┘┴ └───┘ └──┘ ┴ └────────────────┘
typ ┴ ┴ ┴ └─────────┘┴ └───┘ └──┘ ┴ └────────────────┘
489
490 /- range -/
491
492 /-- `range n` is the multiset lifted from the list `range n`,
493 that is, the set `{0, 1, ..., n-1}`. -/
494 def range (n : ℕ) : multiset ℕ := range n
id ┴ └──────┘ ┴ └───┘ ┴
src ┴ └──────┘ ┴ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴
doc └──────┘
495
496 @[simp] theorem range_zero : range 0 = 0 := rfl
id └───┘ ┴ └─┘
src └───┘ ┴ └─┘
typ └───┘ ┴ └─┘
doc └──┘ └───┘
497
498 @[simp] theorem range_succ (n : ℕ) : range (succ n) = n :: range n :=
id ┴ └───┘ └──┘ ┴ ┴ ┴ └┘ └───┘ ┴
src ┴ └───┘ └──┘ ┴ └┘ └───┘
typ ┴ └───┘ └──┘ ┴ ┴ ┴ └┘ └───┘ ┴
doc └──┘ └───┘ └┘ └───┘
499 by rw [range, range_concat, ← coe_add, add_comm]; refl
id └───┘ └──────────┘ └─────┘ └──────┘
src └──┘└───┘└┘└──────────┘└──┘└─────┘└┘└──────┘┴ └────
typ └──┘└───┘└┘└──────────┘└──┘└─────┘└┘└──────┘┴ └────
doc └──┘└───┘└┘ └──┘ └┘ ┴ └────
txt └──┘ └┘ └──┘ └┘ ┴ └────
par └──┘ └┘ └──┘ └┘ ┴ └────
pid └┘ └┘ └──┘ └┘ ┴ └
st └────────┘└────────────┘└─────────┘└────────┘┴└──────
500
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
501 @[simp] theorem card_range (n : ℕ) : card (range n) = n := length_range _
id ┴ └──┘ └───┘ ┴ ┴ ┴ └──────────┘
src ┴ └──┘ └───┘ ┴ └──────────┘
typ ┴ └──┘ └───┘ ┴ ┴ ┴ └──────────┘
doc └──┘ └──┘ └───┘
502
503 theorem range_subset {m n : ℕ} : range m ⊆ range n ↔ m ≤ n := range_subset
id ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └──────────┘
src ┴ └───┘ ┴ └───┘ ┴ ┴ └──────────┘
typ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └──────────┘
doc └───┘ └───┘
504
505 @[simp] theorem mem_range {m n : ℕ} : m ∈ range n ↔ m < n := mem_range
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └───────┘
src ┴ ┴ └───┘ ┴ ┴ └───────┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └───────┘
doc └──┘ └───┘
506
507 @[simp] theorem not_mem_range_self {n : ℕ} : n ∉ range n := not_mem_range_self
id ┴ ┴ ┴ └───┘ ┴ └────────────────┘
src ┴ ┴ └───┘ └────────────────┘
typ ┴ ┴ ┴ └───┘ ┴ └────────────────┘
doc └──┘ └───┘
508
509 /- erase -/
510 section erase
511 variables [decidable_eq α] {s t : multiset α} {a b : α}
id └──────────┘ └──────┘
src └──────────┘ └──────┘
typ └──────────┘ └──────┘
doc └──────┘
512
513 /-- `erase s a` is the multiset that subtracts 1 from the
514 multiplicity of `a`. -/
515 def erase (s : multiset α) (a : α) : multiset α :=
id └──────┘ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘
516 quot.lift_on s (λ l, (l.erase a : multiset α))
id └──────────┘ ┴ ┴ ┴└────┘ ┴ └──────┘ ┴
src └──────────┘ └────┘ └──────┘
typ └──────────┘ ┴ ┴ ┴└────┘ ┴ └──────┘ ┴
doc └──────┘
517 (λ l₁ l₂ p, quot.sound (erase_perm_erase a p))
id └┘ └┘ ┴ └────────┘ └──────────────┘ ┴ ┴
src └────────┘ └──────────────┘
typ └┘ └┘ ┴ └────────┘ └──────────────┘ ┴ ┴
518
519 @[simp] theorem coe_erase (l : list α) (a : α) :
id └──┘ ┴ ┴
src └──┘
typ └──┘ ┴ ┴
doc └──┘
520 erase (l : multiset α) a = l.erase a := rfl
id └───┘ ┴ └──────┘ ┴ ┴ ┴ ┴└────┘ ┴ └─┘
src └───┘ └──────┘ ┴ └────┘ └─┘
typ └───┘ ┴ └──────┘ ┴ ┴ ┴ ┴└────┘ ┴ └─┘
doc └───┘ └──────┘
521
522 @[simp] theorem erase_zero (a : α) : (0 : multiset α).erase a = 0 := rfl
id ┴ └──────┘ ┴ └───┘ ┴ ┴ └─┘
src └──────┘ └───┘ ┴ └─┘
typ ┴ └──────┘ ┴ └───┘ ┴ ┴ └─┘
doc └──┘ └──────┘ └───┘
523
524 @[simp] theorem erase_cons_head (a : α) (s : multiset α) : (a :: s).erase a = s :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ └───┘ ┴ ┴ ┴
src └──────┘ └┘ └───┘ ┴
typ ┴ └──────┘ ┴ ┴ └┘ ┴ └───┘ ┴ ┴ ┴
doc └──┘ └──────┘ └┘ └───┘
525 quot.induction_on s $ λ l, congr_arg coe $ erase_cons_head a l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └─────────────┘ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └─────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └─────────────┘ ┴ ┴
526
527 @[simp] theorem erase_cons_tail {a b : α} (s : multiset α) (h : b ≠ a) : (b::s).erase a = b :: s.erase a :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴└┘┴ └───┘ ┴ ┴ ┴ └┘ ┴└────┘ ┴
src └──────┘ ┴ └┘ └───┘ ┴ └┘ └────┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴└┘┴ └───┘ ┴ ┴ ┴ └┘ ┴└────┘ ┴
doc └──┘ └──────┘ └┘ └───┘ └┘ └────┘
528 quot.induction_on s $ λ l, congr_arg coe $ erase_cons_tail l h
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └─────────────┘ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └─────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └─────────────┘ ┴ ┴
529
530 @[simp] theorem erase_of_not_mem {a : α} {s : multiset α} : a ∉ s → s.erase a = s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴
src └──────┘ ┴ └────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴
doc └──┘ └──────┘ └────┘
531 quot.induction_on s $ λ l h, congr_arg coe $ erase_of_not_mem h
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └──────────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └──────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └──────────────┘ ┴
532
533 @[simp] theorem cons_erase {s : multiset α} {a : α} : a ∈ s → a :: s.erase a = s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴└────┘ ┴ ┴ ┴
src └──────┘ ┴ └┘ └────┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴└────┘ ┴ ┴ ┴
doc └──┘ └──────┘ └┘ └────┘
534 quot.induction_on s $ λ l h, quot.sound (perm_erase h).symm
id └───────────────┘ ┴ ┴ ┴ └────────┘ └────────┘ ┴ └──┘
src └───────────────┘ └────────┘ └────────┘ └──┘
typ └───────────────┘ ┴ ┴ ┴ └────────┘ └────────┘ ┴ └──┘
535
536 theorem le_cons_erase (s : multiset α) (a : α) : s ≤ a :: s.erase a :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴└────┘ ┴
src └──────┘ ┴ └┘ └────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴└────┘ ┴
doc └──────┘ └┘ └────┘
537 if h : a ∈ s then le_of_eq (cons_erase h).symm
id └┘ ┴ ┴ ┴ └──────┘ └────────┘ ┴ └──┘
src └┘ ┴ └──────┘ └────────┘ └──┘
typ └┘ ┴ ┴ ┴ └──────┘ └────────┘ ┴ └──┘
538 else by rw erase_of_not_mem h; apply le_cons_self
id └──────────────┘ ┴ └──────────┘
src └─┘└──────────────┘┴ └────┘└──────────┘└
typ └─┘└──────────────┘┴┴ └────┘└──────────┘└
doc └─┘ ┴ └────┘ └
txt └─┘ ┴ └────┘ └
par └─┘ ┴ └────┘ └
pid ┴ ┴ ┴ └
st └──────────────────────────────────────────
539
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
540 theorem erase_add_left_pos {a : α} {s : multiset α} (t) : a ∈ s → (s + t).erase a = s.erase a + t :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴
src └──────┘ ┴ ┴ └───┘ ┴ └────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴
doc └──────┘ └───┘ └────┘
541 quotient.induction_on₂ s t $ λ l₁ l₂ h, congr_arg coe $ erase_append_left l₂ h
id └────────────────────┘ ┴ ┴ └┘ └┘ ┴ └───────┘ └─┘ └───────────────┘ └┘ ┴
src └────────────────────┘ └───────┘ └─┘ └───────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ ┴ └───────┘ └─┘ └───────────────┘ └┘ ┴
542
543 theorem erase_add_right_pos {a : α} (s) {t : multiset α} (h : a ∈ t) : (s + t).erase a = s + t.erase a :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴
src └──────┘ ┴ ┴ └───┘ ┴ ┴ └────┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴
doc └──────┘ └───┘ └────┘
544 by rw [add_comm, erase_add_left_pos s h, add_comm]
id └──────┘ └────────────────┘ ┴ ┴ └──────┘
src └──┘└──────┘└┘└────────────────┘┴ ┴ └┘└──────┘└─
typ └──┘└──────┘└┘└────────────────┘┴┴┴┴└┘└──────┘└─
doc └──┘ └┘ ┴ ┴ └┘ └─
txt └──┘ └┘ ┴ ┴ └┘ └─
par └──┘ └┘ ┴ ┴ └┘ └─
pid └┘ └┘ ┴ ┴ └┘ ┴└
st └───────────┘└──────────────────────┘└────────┘┴└
545
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
546 theorem erase_add_right_neg {a : α} {s : multiset α} (t) : a ∉ s → (s + t).erase a = s + t.erase a :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴
src └──────┘ ┴ ┴ └───┘ ┴ ┴ └────┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴
doc └──────┘ └───┘ └────┘
547 quotient.induction_on₂ s t $ λ l₁ l₂ h, congr_arg coe $ erase_append_right l₂ h
id └────────────────────┘ ┴ ┴ └┘ └┘ ┴ └───────┘ └─┘ └────────────────┘ └┘ ┴
src └────────────────────┘ └───────┘ └─┘ └────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ ┴ └───────┘ └─┘ └────────────────┘ └┘ ┴
548
549 theorem erase_add_left_neg {a : α} (s) {t : multiset α} (h : a ∉ t) : (s + t).erase a = s.erase a + t :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴
src └──────┘ ┴ ┴ └───┘ ┴ └────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴
doc └──────┘ └───┘ └────┘
550 by rw [add_comm, erase_add_right_neg s h, add_comm]
id └──────┘ └─────────────────┘ ┴ ┴ └──────┘
src └──┘└──────┘└┘└─────────────────┘┴ ┴ └┘└──────┘└─
typ └──┘└──────┘└┘└─────────────────┘┴┴┴┴└┘└──────┘└─
doc └──┘ └┘ ┴ ┴ └┘ └─
txt └──┘ └┘ ┴ ┴ └┘ └─
par └──┘ └┘ ┴ ┴ └┘ └─
pid └┘ └┘ ┴ ┴ └┘ ┴└
st └───────────┘└───────────────────────┘└────────┘┴└
551
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
552 theorem erase_le (a : α) (s : multiset α) : s.erase a ≤ s :=
id ┴ └──────┘ ┴ ┴└────┘ ┴ ┴ ┴
src └──────┘ └────┘ ┴
typ ┴ └──────┘ ┴ ┴└────┘ ┴ ┴ ┴
doc └──────┘ └────┘
553 quot.induction_on s $ λ l, subperm_of_sublist (erase_sublist a l)
id └───────────────┘ ┴ ┴ └────────────────┘ └───────────┘ ┴ ┴
src └───────────────┘ └────────────────┘ └───────────┘
typ └───────────────┘ ┴ ┴ └────────────────┘ └───────────┘ ┴ ┴
554
555 @[simp] theorem erase_lt {a : α} {s : multiset α} : s.erase a < s ↔ a ∈ s :=
id ┴ └──────┘ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └────┘ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └────┘
556 ⟨λ h, not_imp_comm.1 erase_of_not_mem (ne_of_lt h),
id ┴ └──────────┘┴ └──────────────┘ └──────┘ ┴
src └──────────┘┴ └──────────────┘ └──────┘
typ ┴ └──────────┘┴ └──────────────┘ └──────┘ ┴
557 λ h, by simpa [h] using lt_cons_self (s.erase a) a⟩
id ┴ ┴ └──────────┘ └─────┘ ┴
src └─────┘ └──────┘└──────────┘┴ └─────┘┴ └┘
typ ┴ └─────┘┴└──────┘└──────────┘┴ └─────┘┴ └┘┴
doc └─────┘ └──────┘ ┴ └─────┘┴ └┘
txt └─────┘ └──────┘ ┴ ┴ └┘
par └─────┘ └──────┘ ┴ ┴ └┘
pid ┴┴ ┴┴└────┘ ┴ ┴ └┘
st └─────────────────────────────────────────┘
558
559 theorem erase_subset (a : α) (s : multiset α) : s.erase a ⊆ s :=
id ┴ └──────┘ ┴ ┴└────┘ ┴ ┴ ┴
src └──────┘ └────┘ ┴
typ ┴ └──────┘ ┴ ┴└────┘ ┴ ┴ ┴
doc └──────┘ └────┘
560 subset_of_le (erase_le a s)
id └──────────┘ └──────┘ ┴ ┴
src └──────────┘ └──────┘
typ └──────────┘ └──────┘ ┴ ┴
561
562 theorem mem_erase_of_ne {a b : α} {s : multiset α} (ab : a ≠ b) : a ∈ s.erase b ↔ a ∈ s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ └────┘ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └────┘
563 quot.induction_on s $ λ l, list.mem_erase_of_ne ab
id └───────────────┘ ┴ ┴ └──────────────────┘ └┘
src └───────────────┘ └──────────────────┘
typ └───────────────┘ ┴ ┴ └──────────────────┘ └┘
564
565 theorem mem_of_mem_erase {a b : α} {s : multiset α} : a ∈ s.erase b → a ∈ s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ └────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴
doc └──────┘ └────┘
566 mem_of_subset (erase_subset _ _)
id └───────────┘ └──────────┘
src └───────────┘ └──────────┘
typ └───────────┘ └──────────┘
567
568 theorem erase_comm (s : multiset α) (a b : α) : (s.erase a).erase b = (s.erase b).erase a :=
id └──────┘ ┴ ┴ ┴└────┘ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ └───┘ ┴
src └──────┘ └────┘ └───┘ ┴ └────┘ └───┘
typ └──────┘ ┴ ┴ ┴└────┘ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ └───┘ ┴
doc └──────┘ └────┘ └───┘ └────┘ └───┘
569 quot.induction_on s $ λ l, congr_arg coe $ l.erase_comm a b
id └───────────────┘ ┴ ┴ └───────┘ └─┘ ┴└─────────┘ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └─────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ ┴└─────────┘ ┴ ┴
570
571 theorem erase_le_erase {s t : multiset α} (a : α) (h : s ≤ t) : s.erase a ≤ t.erase a :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴└────┘ ┴
src └──────┘ ┴ └────┘ ┴ └────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴└────┘ ┴
doc └──────┘ └────┘ └────┘
572 le_induction_on h $ λ l₁ l₂ h, subperm_of_sublist (erase_sublist_erase _ h)
id └─────────────┘ ┴ └┘ └┘ ┴ └────────────────┘ └─────────────────┘ ┴
src └─────────────┘ └────────────────┘ └─────────────────┘
typ └─────────────┘ ┴ └┘ └┘ ┴ └────────────────┘ └─────────────────┘ ┴
573
574 theorem erase_le_iff_le_cons {s t : multiset α} {a : α} : s.erase a ≤ t ↔ s ≤ a :: t :=
id └──────┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ └────┘ ┴ ┴ ┴ └┘
typ └──────┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └────┘ └┘
575 ⟨λ h, le_trans (le_cons_erase _ _) (cons_le_cons _ h),
id ┴ └──────┘ └───────────┘ └──────────┘ ┴
src └──────┘ └───────────┘ └──────────┘
typ ┴ └──────┘ └───────────┘ └──────────┘ ┴
576 λ h, if m : a ∈ s
id ┴ └┘ ┴ ┴ ┴
src └┘ ┴
typ ┴ └┘ ┴ ┴ ┴
577 then by rw ← cons_erase m at h; exact (cons_le_cons_iff _).1 h
id └────────┘ ┴ └──────────────┘ ┴
src └───┘└────────┘┴ └───┘ └────┘ └──────────────┘└────┘ └
typ └───┘└────────┘┴┴└───┘ └────┘ └──────────────┘└────┘┴└
doc └───┘ ┴ └───┘ └────┘ └────┘ └
txt └───┘ ┴ └───┘ └────┘ └────┘ └
par └───┘ ┴ └───┘ └────┘ └────┘ └
pid └─┘ ┴ └───┘ ┴ └────┘ └
st └───────────────────────────────────────────────────────
578 else le_trans (erase_le _ _) ((le_cons_of_not_mem m).1 h)⟩
id └──────┘ └──────┘ └────────────────┘ ┴ ┴ ┴
src ─┘ └──────┘ └──────┘ └────────────────┘ ┴
typ ─┘ └──────┘ └──────┘ └────────────────┘ ┴ ┴ ┴
doc ─┘
txt ─┘
par ─┘
pid ─┘
st ─┘
579
580 @[simp] theorem card_erase_of_mem {a : α} {s : multiset α} : a ∈ s → card (s.erase a) = pred (card s) :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴└────┘ ┴ ┴ └──┘ └──┘ ┴
src └──────┘ ┴ └──┘ └────┘ ┴ └──┘ └──┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴└────┘ ┴ ┴ └──┘ └──┘ ┴
doc └──┘ └──────┘ └──┘ └────┘ └──┘
581 quot.induction_on s $ λ l, length_erase_of_mem
id └───────────────┘ ┴ ┴ └─────────────────┘
src └───────────────┘ └─────────────────┘
typ └───────────────┘ ┴ ┴ └─────────────────┘
582
583 theorem card_erase_lt_of_mem {a : α} {s : multiset α} : a ∈ s → card (s.erase a) < card s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴└────┘ ┴ ┴ └──┘ ┴
src └──────┘ ┴ └──┘ └────┘ ┴ └──┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴└────┘ ┴ ┴ └──┘ ┴
doc └──────┘ └──┘ └────┘ └──┘
584 λ h, card_lt_of_lt (erase_lt.mpr h)
id ┴ └───────────┘ └──────┘└──┘ ┴
src └───────────┘ └──────┘└──┘
typ ┴ └───────────┘ └──────┘└──┘ ┴
585
586 theorem card_erase_le {a : α} {s : multiset α} : card (s.erase a) ≤ card s :=
id ┴ └──────┘ ┴ └──┘ ┴└────┘ ┴ ┴ └──┘ ┴
src └──────┘ └──┘ └────┘ ┴ └──┘
typ ┴ └──────┘ ┴ └──┘ ┴└────┘ ┴ ┴ └──┘ ┴
doc └──────┘ └──┘ └────┘ └──┘
587 card_le_of_le (erase_le a s)
id └───────────┘ └──────┘ ┴ ┴
src └───────────┘ └──────┘
typ └───────────┘ └──────┘ ┴ ┴
588
589 end erase
590
591 @[simp] theorem coe_reverse (l : list α) : (reverse l : multiset α) = l :=
id └──┘ ┴ └─────┘ ┴ └──────┘ ┴ ┴ ┴
src └──┘ └─────┘ └──────┘ ┴
typ └──┘ ┴ └─────┘ ┴ └──────┘ ┴ ┴ ┴
doc └──┘ └──────┘
592 quot.sound $ reverse_perm _
id └────────┘ └──────────┘
src └────────┘ └──────────┘
typ └────────┘ └──────────┘
593
594 /- map -/
595
596 /-- `map f s` is the lift of the list `map` operation. The multiplicity
597 of `b` in `map f s` is the number of `a ∈ s` (counting multiplicity)
598 such that `f a = b`. -/
599 def map (f : α → β) (s : multiset α) : multiset β :=
id ┴ ┴ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
600 quot.lift_on s (λ l : list α, (l.map f : multiset β))
id └──────────┘ ┴ └──┘ ┴ ┴└──┘ ┴ └──────┘ ┴
src └──────────┘ └──┘ └──┘ └──────┘
typ └──────────┘ ┴ └──┘ ┴ ┴└──┘ ┴ └──────┘ ┴
doc └──────┘
601 (λ l₁ l₂ p, quot.sound (perm_map f p))
id └┘ └┘ ┴ └────────┘ └──────┘ ┴ ┴
src └────────┘ └──────┘
typ └┘ └┘ ┴ └────────┘ └──────┘ ┴ ┴
602
603 @[simp] theorem coe_map (f : α → β) (l : list α) : map f ↑l = l.map f := rfl
id ┴ ┴ └──┘ ┴ └─┘ ┴ ┴┴ ┴ ┴└──┘ ┴ └─┘
src └──┘ └─┘ ┴ ┴ └──┘ └─┘
typ ┴ ┴ └──┘ ┴ └─┘ ┴ ┴┴ ┴ ┴└──┘ ┴ └─┘
doc └──┘ └─┘
604
605 @[simp] theorem map_zero (f : α → β) : map f 0 = 0 := rfl
id ┴ ┴ └─┘ ┴ ┴ └─┘
src └─┘ ┴ └─┘
typ ┴ ┴ └─┘ ┴ ┴ └─┘
doc └──┘ └─┘
606
607 @[simp] theorem map_cons (f : α → β) (a s) : map f (a::s) = f a :: map f s :=
id ┴ ┴ └─┘ ┴ ┴└┘┴ ┴ ┴ ┴ └┘ └─┘ ┴ ┴
src └─┘ └┘ ┴ └┘ └─┘
typ ┴ ┴ └─┘ ┴ ┴└┘┴ ┴ ┴ ┴ └┘ └─┘ ┴ ┴
doc └──┘ └─┘ └┘ └┘ └─┘
608 quot.induction_on s $ λ l, rfl
id └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ └───────────────┘ ┴ ┴ └─┘
609
610 @[simp] lemma map_singleton (f : α → β) (a : α) : ({a} : multiset α).map f = {f a} := rfl
id ┴ ┴ ┴ ┴┴ └──────┘ ┴ └─┘ ┴ ┴ ┴┴ ┴ └─┘
src ┴ └──────┘ └─┘ ┴ ┴ └─┘
typ ┴ ┴ ┴ ┴┴ └──────┘ ┴ └─┘ ┴ ┴ ┴┴ ┴ └─┘
doc └──┘ └──────┘ └─┘
611
612 @[simp] theorem map_add (f : α → β) (s t) : map f (s + t) = map f s + map f t :=
id ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
src └─┘ ┴ ┴ └─┘ ┴ └─┘
typ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
doc └──┘ └─┘ └─┘ └─┘
613 quotient.induction_on₂ s t $ λ l₁ l₂, congr_arg coe $ map_append _ _ _
id └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └────────┘
src └────────────────────┘ └───────┘ └─┘ └────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └────────┘
614
615 instance (f : α → β) : is_add_monoid_hom (map f) :=
id ┴ ┴ └───────────────┘ └─┘ ┴
src └───────────────┘ └─┘
typ ┴ ┴ └───────────────┘ └─┘ ┴
doc └───────────────┘ └─┘
616 { map_add := map_add _, map_zero := map_zero _ }
id └─────┘ └──────┘
src └─────┘ └──────┘
typ └─────┘ └──────┘
617
618 @[simp] theorem mem_map {f : α → β} {b : β} {s : multiset α} :
id ┴ ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘
619 b ∈ map f s ↔ ∃ a, a ∈ s ∧ f a = b :=
id ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘
620 quot.induction_on s $ λ l, mem_map
id └───────────────┘ ┴ ┴ └─────┘
src └───────────────┘ └─────┘
typ └───────────────┘ ┴ ┴ └─────┘
621
622 @[simp] theorem card_map (f : α → β) (s) : card (map f s) = card s :=
id ┴ ┴ └──┘ └─┘ ┴ ┴ ┴ └──┘ ┴
src └──┘ └─┘ ┴ └──┘
typ ┴ ┴ └──┘ └─┘ ┴ ┴ ┴ └──┘ ┴
doc └──┘ └──┘ └─┘ └──┘
623 quot.induction_on s $ λ l, length_map _ _
id └───────────────┘ ┴ ┴ └────────┘
src └───────────────┘ └────────┘
typ └───────────────┘ ┴ ┴ └────────┘
624
625 @[simp] theorem map_eq_zero {s : multiset α} {f : α → β} : s.map f = 0 ↔ s = 0 :=
id └──────┘ ┴ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──┘
626 by rw [← multiset.card_eq_zero, multiset.card_map, multiset.card_eq_zero]
id └───────────────────┘ └───────────────┘ └───────────────────┘
src └────┘└───────────────────┘└┘└───────────────┘└┘└───────────────────┘└─
typ └────┘└───────────────────┘└┘└───────────────┘└┘└───────────────────┘└─
doc └────┘ └┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid └──┘ └┘ └┘ ┴└
st └──────────────────────────┘└─────────────────┘└─────────────────────┘┴└
627
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
628 theorem mem_map_of_mem (f : α → β) {a : α} {s : multiset α} (h : a ∈ s) : f a ∈ map f s :=
id ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
src └──────┘ ┴ ┴ └─┘
typ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
doc └──────┘ └─┘
629 mem_map.2 ⟨_, h, rfl⟩
id └─────┘┴ ┴ └─┘
src └─────┘┴ └─┘
typ └─────┘┴ ┴ └─┘
630
631 @[simp] theorem mem_map_of_inj {f : α → β} (H : function.injective f) {a : α} {s : multiset α} :
id ┴ ┴ └────────────────┘ ┴ ┴ └──────┘ ┴
src └────────────────┘ └──────┘
typ ┴ ┴ └────────────────┘ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘
632 f a ∈ map f s ↔ a ∈ s :=
id ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └─┘ ┴ ┴
typ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘
633 quot.induction_on s $ λ l, mem_map_of_inj H
id └───────────────┘ ┴ ┴ └────────────┘ ┴
src └───────────────┘ └────────────┘
typ └───────────────┘ ┴ ┴ └────────────┘ ┴
634
635 @[simp] theorem map_map (g : β → γ) (f : α → β) (s : multiset α) : map g (map f s) = map (g ∘ f) s :=
id ┴ ┴ ┴ ┴ └──────┘ ┴ └─┘ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴
src └──────┘ └─┘ └─┘ ┴ └─┘ ┴
typ ┴ ┴ ┴ ┴ └──────┘ ┴ └─┘ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └─┘ └─┘ └─┘
636 quot.induction_on s $ λ l, congr_arg coe $ list.map_map _ _ _
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └──────────┘
src └───────────────┘ └───────┘ └─┘ └──────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └──────────┘
637
638 @[simp] theorem map_id (s : multiset α) : map id s = s :=
id └──────┘ ┴ └─┘ └┘ ┴ ┴ ┴
src └──────┘ └─┘ └┘ ┴
typ └──────┘ ┴ └─┘ └┘ ┴ ┴ ┴
doc └──┘ └──────┘ └─┘
639 quot.induction_on s $ λ l, congr_arg coe $ map_id _
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └────┘
src └───────────────┘ └───────┘ └─┘ └────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └────┘
640
641 @[simp] lemma map_id' (s : multiset α) : map (λx, x) s = s := map_id s
id └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴
src └──────┘ └─┘ ┴ └────┘
typ └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴
doc └──┘ └──────┘ └─┘
642
643 @[simp] theorem map_const (s : multiset α) (b : β) : map (function.const α b) s = repeat b s.card :=
id └──────┘ ┴ ┴ └─┘ └────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴└───┘
src └──────┘ └─┘ └────────────┘ ┴ └────┘ └───┘
typ └──────┘ ┴ ┴ └─┘ └────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴└───┘
doc └──┘ └──────┘ └─┘ └────┘ └───┘
644 quot.induction_on s $ λ l, congr_arg coe $ map_const _ _
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────┘
src └───────────────┘ └───────┘ └─┘ └───────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────┘
645
646 @[congr] theorem map_congr {f g : α → β} {s : multiset α} : (∀ x ∈ s, f x = g x) → map f s = map g s :=
id ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
src └───┘ └──────┘ ┴ └─┘ ┴ └─┘
typ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
doc └───┘ └──────┘ └─┘ └─┘
647 quot.induction_on s $ λ l H, congr_arg coe $ map_congr H
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────┘ ┴
src └───────────────┘ └───────┘ └─┘ └───────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────┘ ┴
648
649 lemma map_hcongr {β' : Type*} {m : multiset α} {f : α → β} {f' : α → β'}
id └──────┘ ┴ ┴ ┴ ┴ └┘
src └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ └┘
doc └──────┘
650 (h : β = β') (hf : ∀a∈m, f a == f' a) : map f m == map f' m :=
id ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘ └┘ ┴ └─┘ ┴ ┴ └┘ └─┘ └┘ ┴
src ┴ └┘ └─┘ └┘ └─┘
typ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘ └┘ ┴ └─┘ ┴ ┴ └┘ └─┘ └┘ ┴
doc └─┘ └─┘
651 begin subst h, simp at hf, simp [map_congr hf] end
id ┴ └───────┘ └┘
src └────┘ └────────┘ └────┘└───────┘┴ └┘
typ └────┘┴ └────────┘ └────┘└───────┘┴└┘└┘
doc └────┘ └────────┘ └────┘ ┴ └┘
txt └────┘ └────────┘ └────┘ ┴ └┘
par └────┘ └────────┘ └────┘ ┴ └┘
pid ┴ ┴└───┘ ┴┴ ┴ ┴┴
st └───────────┘└──────────┘└────────────────────┘└─┘
652
653 theorem eq_of_mem_map_const {b₁ b₂ : β} {l : list α} (h : b₁ ∈ map (function.const α b₂) l) : b₁ = b₂ :=
id ┴ └──┘ ┴ └┘ ┴ └─┘ └────────────┘ ┴ └┘ ┴ └┘ ┴ └┘
src └──┘ ┴ └─┘ └────────────┘ ┴
typ ┴ └──┘ ┴ └┘ ┴ └─┘ └────────────┘ ┴ └┘ ┴ └┘ ┴ └┘
doc └─┘
654 eq_of_mem_repeat $ by rwa map_const at h
id └──────────────┘ └───────┘
src └──────────────┘ └──┘└───────┘└─────
typ └──────────────┘ └──┘└───────┘└─────
doc └──┘ └─────
txt └──┘ └─────
par └──┘ └─────
pid ┴ └───┘└
st └───────────────────
655
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
656 @[simp] theorem map_le_map {f : α → β} {s t : multiset α} (h : s ≤ t) : map f s ≤ map f t :=
id ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
src └──────┘ ┴ └─┘ ┴ └─┘
typ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
doc └──┘ └──────┘ └─┘ └─┘
657 le_induction_on h $ λ l₁ l₂ h, subperm_of_sublist $ map_sublist_map f h
id └─────────────┘ ┴ └┘ └┘ ┴ └────────────────┘ └─────────────┘ ┴ ┴
src └─────────────┘ └────────────────┘ └─────────────┘
typ └─────────────┘ ┴ └┘ └┘ ┴ └────────────────┘ └─────────────┘ ┴ ┴
658
659 @[simp] theorem map_subset_map {f : α → β} {s t : multiset α} (H : s ⊆ t) : map f s ⊆ map f t :=
id ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
src └──────┘ ┴ └─┘ ┴ └─┘
typ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
doc └──┘ └──────┘ └─┘ └─┘
660 λ b m, let ⟨a, h, e⟩ := mem_map.1 m in mem_map.2 ⟨a, H h, e⟩
id ┴ ┴ └─┘ ┴ ┴ ┴ └─────┘┴ ┴ └─────┘┴ ┴
src └─────┘┴ └─────┘┴
typ ┴ ┴ └─┘ ┴ ┴ ┴ └─────┘┴ ┴ └─────┘┴ ┴
661
662 /- fold -/
663
664 /-- `foldl f H b s` is the lift of the list operation `foldl f b l`,
665 which folds `f` over the multiset. It is well defined when `f` is right-commutative,
666 that is, `f (f b a₁) a₂ = f (f b a₂) a₁`. -/
667 def foldl (f : β → α → β) (H : right_commutative f) (b : β) (s : multiset α) : β :=
id ┴ ┴ ┴ └───────────────┘ ┴ ┴ └──────┘ ┴ ┴
src └───────────────┘ └──────┘
typ ┴ ┴ ┴ └───────────────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘
668 quot.lift_on s (λ l, foldl f b l)
id └──────────┘ ┴ ┴ └───┘ ┴ ┴ ┴
src └──────────┘ └───┘
typ └──────────┘ ┴ ┴ └───┘ ┴ ┴ ┴
669 (λ l₁ l₂ p, foldl_eq_of_perm H p b)
id └┘ └┘ ┴ └──────────────┘ ┴ ┴ ┴
src └──────────────┘
typ └┘ └┘ ┴ └──────────────┘ ┴ ┴ ┴
670
671 @[simp] theorem foldl_zero (f : β → α → β) (H b) : foldl f H b 0 = b := rfl
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘
src └───┘ ┴ └─┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘
doc └──┘ └───┘
672
673 @[simp] theorem foldl_cons (f : β → α → β) (H b a s) : foldl f H b (a :: s) = foldl f H (f b a) s :=
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴
src └───┘ └┘ ┴ └───┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └───┘ └┘ └───┘
674 quot.induction_on s $ λ l, rfl
id └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ └───────────────┘ ┴ ┴ └─┘
675
676 @[simp] theorem foldl_add (f : β → α → β) (H b s t) : foldl f H b (s + t) = foldl f H (foldl f H b s) t :=
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
src └───┘ ┴ ┴ └───┘ └───┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └───┘ └───┘ └───┘
677 quotient.induction_on₂ s t $ λ l₁ l₂, foldl_append _ _ _ _
id └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘
src └────────────────────┘ └──────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘
678
679 /-- `foldr f H b s` is the lift of the list operation `foldr f b l`,
680 which folds `f` over the multiset. It is well defined when `f` is left-commutative,
681 that is, `f a₁ (f a₂ b) = f a₂ (f a₁ b)`. -/
682 def foldr (f : α → β → β) (H : left_commutative f) (b : β) (s : multiset α) : β :=
id ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────────────┘ └──────┘
typ ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘
683 quot.lift_on s (λ l, foldr f b l)
id └──────────┘ ┴ ┴ └───┘ ┴ ┴ ┴
src └──────────┘ └───┘
typ └──────────┘ ┴ ┴ └───┘ ┴ ┴ ┴
684 (λ l₁ l₂ p, foldr_eq_of_perm H p b)
id └┘ └┘ ┴ └──────────────┘ ┴ ┴ ┴
src └──────────────┘
typ └┘ └┘ ┴ └──────────────┘ ┴ ┴ ┴
685
686 @[simp] theorem foldr_zero (f : α → β → β) (H b) : foldr f H b 0 = b := rfl
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘
src └───┘ ┴ └─┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘
doc └──┘ └───┘
687
688 @[simp] theorem foldr_cons (f : α → β → β) (H b a s) : foldr f H b (a :: s) = f a (foldr f H b s) :=
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴
src └───┘ └┘ ┴ └───┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴
doc └──┘ └───┘ └┘ └───┘
689 quot.induction_on s $ λ l, rfl
id └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ └───────────────┘ ┴ ┴ └─┘
690
691 @[simp] theorem foldr_add (f : α → β → β) (H b s t) : foldr f H b (s + t) = foldr f H (foldr f H b t) s :=
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
src └───┘ ┴ ┴ └───┘ └───┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └───┘ └───┘ └───┘
692 quotient.induction_on₂ s t $ λ l₁ l₂, foldr_append _ _ _ _
id └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘
src └────────────────────┘ └──────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘
693
694 @[simp] theorem coe_foldr (f : α → β → β) (H : left_commutative f) (b : β) (l : list α) :
id ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──┘ ┴
src └──────────────┘ └──┘
typ ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──┘ ┴
doc └──┘
695 foldr f H b l = l.foldr f b := rfl
id └───┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ └─┘
src └───┘ ┴ └────┘ └─┘
typ └───┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ └─┘
doc └───┘
696
697 @[simp] theorem coe_foldl (f : β → α → β) (H : right_commutative f) (b : β) (l : list α) :
id ┴ ┴ ┴ └───────────────┘ ┴ ┴ └──┘ ┴
src └───────────────┘ └──┘
typ ┴ ┴ ┴ └───────────────┘ ┴ ┴ └──┘ ┴
doc └──┘
698 foldl f H b l = l.foldl f b := rfl
id └───┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ └─┘
src └───┘ ┴ └────┘ └─┘
typ └───┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ └─┘
doc └───┘
699
700 theorem coe_foldr_swap (f : α → β → β) (H : left_commutative f) (b : β) (l : list α) :
id ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──┘ ┴
src └──────────────┘ └──┘
typ ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──┘ ┴
701 foldr f H b l = l.foldl (λ x y, f y x) b :=
id └───┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └───┘ ┴ └────┘
typ └───┘ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └───┘
702 (congr_arg (foldr f H b) (coe_reverse l)).symm.trans $ foldr_reverse _ _ _
id └───────┘ └───┘ ┴ ┴ ┴ └─────────┘ ┴ └──┘ └───┘ └───────────┘
src └───────┘ └───┘ └─────────┘ └──┘ └───┘ └───────────┘
typ └───────┘ └───┘ ┴ ┴ ┴ └─────────┘ ┴ └──┘ └───┘ └───────────┘
doc └───┘
703
704 theorem foldr_swap (f : α → β → β) (H : left_commutative f) (b : β) (s : multiset α) :
id ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──────┘ ┴
src └──────────────┘ └──────┘
typ ┴ ┴ ┴ └──────────────┘ ┴ ┴ └──────┘ ┴
doc └──────┘
705 foldr f H b s = foldl (λ x y, f y x) (λ x y z, (H _ _ _).symm) b s :=
id └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
src └───┘ ┴ └───┘ └──┘
typ └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
doc └───┘ └───┘
706 quot.induction_on s $ λ l, coe_foldr_swap _ _ _ _
id └───────────────┘ ┴ ┴ └────────────┘
src └───────────────┘ └────────────┘
typ └───────────────┘ ┴ ┴ └────────────┘
707
708 theorem foldl_swap (f : β → α → β) (H : right_commutative f) (b : β) (s : multiset α) :
id ┴ ┴ ┴ └───────────────┘ ┴ ┴ └──────┘ ┴
src └───────────────┘ └──────┘
typ ┴ ┴ ┴ └───────────────┘ ┴ ┴ └──────┘ ┴
doc └──────┘
709 foldl f H b s = foldr (λ x y, f y x) (λ x y z, (H _ _ _).symm) b s :=
id └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
src └───┘ ┴ └───┘ └──┘
typ └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
doc └───┘ └───┘
710 (foldr_swap _ _ _ _).symm
id └────────┘ └──┘
src └────────┘ └──┘
typ └────────┘ └──┘
711
712 /-- Product of a multiset given a commutative monoid structure on `α`.
713 `prod {a, b, c} = a * b * c` -/
714 @[to_additive]
doc └─────────┘
715 def prod [comm_monoid α] : multiset α → α :=
id └─────────┘ ┴ └──────┘ ┴ ┴
src └─────────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴ ┴
doc └──────┘
716 foldr (*) (λ x y z, by simp [mul_left_comm]) 1
id └───┘ ┴ ┴ ┴ ┴ └───────────┘
src └───┘ ┴ └────┘└───────────┘┴
typ └───┘ ┴ ┴ ┴ ┴ └────┘└───────────┘┴
doc └───┘ └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └───────────────────┘
717
718 @[to_additive]
doc └─────────┘
719 theorem prod_eq_foldr [comm_monoid α] (s : multiset α) :
id └─────────┘ ┴ └──────┘ ┴
src └─────────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴
doc └──────┘
720 prod s = foldr (*) (λ x y z, by simp [mul_left_comm]) 1 s := rfl
id └──┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └───────────┘ ┴ └─┘
src └──┘ ┴ └───┘ ┴ └────┘└───────────┘┴ └─┘
typ └──┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └────┘└───────────┘┴ ┴ └─┘
doc └──┘ └───┘ └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └───────────────────┘
721
722 @[to_additive]
doc └─────────┘
723 theorem prod_eq_foldl [comm_monoid α] (s : multiset α) :
id └─────────┘ ┴ └──────┘ ┴
src └─────────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴
doc └──────┘
724 prod s = foldl (*) (λ x y z, by simp [mul_right_comm]) 1 s :=
id └──┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └────────────┘ ┴
src └──┘ ┴ └───┘ ┴ └────┘└────────────┘┴
typ └──┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ └────┘└────────────┘┴ ┴
doc └──┘ └───┘ └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └────────────────────┘
725 (foldr_swap _ _ _ _).trans (by simp [mul_comm])
id └────────┘ └───┘ └──────┘
src └────────┘ └───┘ └────┘└──────┘┴
typ └────────┘ └───┘ └────┘└──────┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └──────────────┘
726
727 @[simp, to_additive]
doc └──┘ └─────────┘
728 theorem coe_prod [comm_monoid α] (l : list α) : prod ↑l = l.prod :=
id └─────────┘ ┴ └──┘ ┴ └──┘ ┴┴ ┴ ┴└───┘
src └─────────┘ └──┘ └──┘ ┴ ┴ └───┘
typ └─────────┘ ┴ └──┘ ┴ └──┘ ┴┴ ┴ ┴└───┘
doc └──┘ └───┘
729 prod_eq_foldl _
id └───────────┘
src └───────────┘
typ └───────────┘
730
731 @[simp, to_additive]
doc └──┘ └─────────┘
732 theorem prod_zero [comm_monoid α] : @prod α _ 0 = 1 := rfl
id └─────────┘ ┴ └──┘ ┴ ┴ └─┘
src └─────────┘ └──┘ ┴ └─┘
typ └─────────┘ ┴ └──┘ ┴ ┴ └─┘
doc └──┘
733
734 @[simp, to_additive]
doc └──┘ └─────────┘
735 theorem prod_cons [comm_monoid α] (a : α) (s) : prod (a :: s) = a * prod s :=
id └─────────┘ ┴ ┴ └──┘ ┴ └┘ ┴ ┴ ┴ ┴ └──┘ ┴
src └─────────┘ └──┘ └┘ ┴ ┴ └──┘
typ └─────────┘ ┴ ┴ └──┘ ┴ └┘ ┴ ┴ ┴ ┴ └──┘ ┴
doc └──┘ └┘ └──┘
736 foldr_cons _ _ _ _ _
id └────────┘
src └────────┘
typ └────────┘
737
738 @[to_additive]
doc └─────────┘
739 theorem prod_singleton [comm_monoid α] (a : α) : prod (a :: 0) = a := by simp
id └─────────┘ ┴ ┴ └──┘ ┴ └┘ ┴ ┴
src └─────────┘ └──┘ └┘ ┴ └────
typ └─────────┘ ┴ ┴ └──┘ ┴ └┘ ┴ ┴ └────
doc └──┘ └┘ └────
txt └────
par └────
pid └
st └─────
740
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
741 @[simp, to_additive]
doc └──┘ └─────────┘
742 theorem prod_add [comm_monoid α] (s t : multiset α) : prod (s + t) = prod s * prod t :=
id └─────────┘ ┴ └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
src └─────────┘ └──────┘ └──┘ ┴ ┴ └──┘ ┴ └──┘
typ └─────────┘ ┴ └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
doc └──────┘ └──┘ └──┘ └──┘
743 quotient.induction_on₂ s t $ λ l₁ l₂, by simp
id └────────────────────┘ ┴ ┴ └┘ └┘
src └────────────────────┘ └────
typ └────────────────────┘ ┴ ┴ └┘ └┘ └────
doc └────
txt └────
par └────
pid └
st └─────
744
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
745 instance sum.is_add_monoid_hom [add_comm_monoid α] : is_add_monoid_hom (sum : multiset α → α) :=
id └─────────────┘ ┴ └───────────────┘ └─┘ └──────┘ ┴ ┴
src └─────────────┘ └───────────────┘ └─┘ └──────┘
typ └─────────────┘ ┴ └───────────────┘ └─┘ └──────┘ ┴ ┴
doc └───────────────┘ └──────┘
746 { map_add := sum_add, map_zero := sum_zero }
id └─────┘ └──────┘
src └─────┘ └──────┘
typ └─────┘ └──────┘
747
748 lemma prod_smul {α : Type*} [comm_monoid α] (m : multiset α) :
id └─────────┘ ┴ └──────┘ ┴
src └─────────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴
doc └──────┘
749 ∀n, (add_monoid.smul n m).prod = m.prod ^ n
id ┴ └─────────────┘ ┴ ┴ └──┘ ┴ ┴└───┘ ┴ ┴
src └─────────────┘ └──┘ ┴ └───┘ ┴
typ ┴ └─────────────┘ ┴ ┴ └──┘ ┴ ┴└───┘ ┴ ┴
doc └──┘ └───┘
750 | 0 := rfl
id └─┘
src └─┘
typ └─┘
751 | (n + 1) :=
id ┴
src ┴
typ ┴
752 by rw [add_monoid.add_smul, add_monoid.one_smul, _root_.pow_add, _root_.pow_one, prod_add, prod_smul n]
id └─────────────────┘ └─────────────────┘ └────────────┘ └────────────┘ └──────┘ └───────┘ ┴
src └──┘└─────────────────┘└┘└─────────────────┘└┘└────────────┘└┘└────────────┘└┘└──────┘└┘ ┴ └─
typ └──┘└─────────────────┘└┘└─────────────────┘└┘└────────────┘└┘└────────────┘└┘└──────┘└┘└───────┘┴┴└─
doc └──┘ └┘ └┘ └┘ └┘ └┘ ┴ └─
txt └──┘ └┘ └┘ └┘ └┘ └┘ ┴ └─
par └──┘ └┘ └┘ └┘ └┘ └┘ ┴ └─
pid └┘ └┘ └┘ └┘ └┘ └┘ ┴ ┴└
st └──────────────────────┘└───────────────────┘└──────────────┘└──────────────┘└────────┘└───────────┘┴└
753
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
754 @[simp] theorem prod_repeat [comm_monoid α] (a : α) (n : ℕ) : prod (multiset.repeat a n) = a ^ n :=
id └─────────┘ ┴ ┴ ┴ └──┘ └─────────────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └─────────┘ ┴ └──┘ └─────────────┘ ┴ ┴
typ └─────────┘ ┴ ┴ ┴ └──┘ └─────────────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──┘ └─────────────┘
755 by simp [repeat, list.prod_repeat]
id └────┘ └──────────────┘
src └────┘└────┘└┘└──────────────┘└┘
typ └────┘└────┘└┘└──────────────┘└┘
doc └────┘└────┘└┘ └┘
txt └────┘ └┘ └┘
par └────┘ └┘ └┘
pid ┴┴ └┘ ┴┴
st └───────────────────────────────┘
756 @[simp] theorem sum_repeat [add_comm_monoid α] : ∀ (a : α) (n : ℕ), sum (multiset.repeat a n) = n • a :=
id └─────────────┘ ┴ ┴ ┴ └─┘ └─────────────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └─────────────┘ ┴ └─┘ └─────────────┘ ┴ ┴
typ └─────────────┘ ┴ ┴ ┴ └─┘ └─────────────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └─────────────┘
757 @prod_repeat (multiplicative α) _
id └─────────┘ └────────────┘ ┴
src └─────────┘ └────────────┘
typ └─────────┘ └────────────┘ ┴
758 attribute [to_additive] prod_repeat
id └─────────┘
src └─────────┘
typ └─────────┘
doc └─────────┘
759
760 @[simp] lemma prod_map_one [comm_monoid γ] {m : multiset α} :
id └─────────┘ ┴ └──────┘ ┴
src └─────────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
761 prod (m.map (λa, (1 : γ))) = (1 : γ) :=
id └──┘ ┴└──┘ ┴ ┴ ┴ ┴
src └──┘ └──┘ ┴
typ └──┘ ┴└──┘ ┴ ┴ ┴ ┴
doc └──┘ └──┘
762 multiset.induction_on m (by simp) (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘ └──┘
typ └───────────────────┘ ┴ └──┘ └──┘
doc └──┘ └──┘
txt └──┘ └──┘
par └──┘ └──┘
st └───┘ └───┘
763 @[simp] lemma sum_map_zero [add_comm_monoid γ] {m : multiset α} :
id └─────────────┘ ┴ └──────┘ ┴
src └─────────────┘ └──────┘
typ └─────────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
764 sum (m.map (λa, (0 : γ))) = (0 : γ) :=
id └─┘ ┴└──┘ ┴ ┴ ┴ ┴
src └─┘ └──┘ ┴
typ └─┘ ┴└──┘ ┴ ┴ ┴ ┴
doc └──┘
765 multiset.induction_on m (by simp) (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘ └──┘
typ └───────────────────┘ ┴ └──┘ └──┘
doc └──┘ └──┘
txt └──┘ └──┘
par └──┘ └──┘
st └───┘ └───┘
766 attribute [to_additive] prod_map_one
id └──────────┘
src └──────────┘
typ └──────────┘
doc └─────────┘
767
768 @[simp, to_additive]
doc └──┘ └─────────┘
769 lemma prod_map_mul [comm_monoid γ] {m : multiset α} {f g : α → γ} :
id └─────────┘ ┴ └──────┘ ┴ ┴ ┴
src └─────────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘
770 prod (m.map $ λa, f a * g a) = prod (m.map f) * prod (m.map g) :=
id └──┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ ┴ └──┘ ┴└──┘ ┴
src └──┘ └──┘ ┴ ┴ └──┘ └──┘ ┴ └──┘ └──┘
typ └──┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ ┴ └──┘ ┴└──┘ ┴
doc └──┘ └──┘ └──┘ └──┘ └──┘ └──┘
771 multiset.induction_on m (by simp) (assume a m ih, by simp [ih]; cc)
id └───────────────────┘ ┴ ┴ ┴ └┘ └┘
src └───────────────────┘ └──┘ └────┘ ┴ └┘
typ └───────────────────┘ ┴ └──┘ ┴ ┴ └┘ └────┘└┘┴ └┘
doc └──┘ └────┘ ┴ └┘
txt └──┘ └────┘ ┴ └┘
par └──┘ └────┘ ┴ └┘
pid ┴┴ ┴
st └───┘ └────────────┘
772
773 lemma prod_map_prod_map [comm_monoid γ] (m : multiset α) (n : multiset β) {f : α → β → γ} :
id └─────────┘ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
src └─────────┘ └──────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘
774 prod (m.map $ λa, prod $ n.map $ λb, f a b) = prod (n.map $ λb, prod $ m.map $ λa, f a b) :=
id └──┘ ┴└──┘ ┴ └──┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ └──┘ ┴└──┘ ┴ ┴ ┴ ┴
src └──┘ └──┘ └──┘ └──┘ ┴ └──┘ └──┘ └──┘ └──┘
typ └──┘ ┴└──┘ ┴ └──┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ └──┘ ┴└──┘ ┴ ┴ ┴ ┴
doc └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘
775 multiset.induction_on m (by simp) (assume a m ih, by simp [ih])
id └───────────────────┘ ┴ ┴ ┴ └┘ └┘
src └───────────────────┘ └──┘ └────┘ ┴
typ └───────────────────┘ ┴ └──┘ ┴ ┴ └┘ └────┘└┘┴
doc └──┘ └────┘ ┴
txt └──┘ └────┘ ┴
par └──┘ └────┘ ┴
pid ┴┴ ┴
st └───┘ └────────┘
776
777 lemma sum_map_sum_map [add_comm_monoid γ] : ∀ (m : multiset α) (n : multiset β) {f : α → β → γ},
id └─────────────┘ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴
src └─────────────┘ └──────┘ └──────┘
typ └─────────────┘ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘
778 sum (m.map $ λa, sum $ n.map $ λb, f a b) = sum (n.map $ λb, sum $ m.map $ λa, f a b) :=
id └─┘ ┴└──┘ ┴ └─┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴└──┘ ┴ └─┘ ┴└──┘ ┴ ┴ ┴ ┴
src └─┘ └──┘ └─┘ └──┘ ┴ └─┘ └──┘ └─┘ └──┘
typ └─┘ ┴└──┘ ┴ └─┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴└──┘ ┴ └─┘ ┴└──┘ ┴ ┴ ┴ ┴
doc └──┘ └──┘ └──┘ └──┘
779 @prod_map_prod_map _ _ (multiplicative γ) _
id └───────────────┘ └────────────┘ ┴
src └───────────────┘ └────────────┘
typ └───────────────┘ └────────────┘ ┴
780 attribute [to_additive] prod_map_prod_map
id └───────────────┘
src └───────────────┘
typ └───────────────┘
doc └─────────┘
781
782 lemma sum_map_mul_left [semiring β] {b : β} {s : multiset α} {f : α → β} :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘
783 sum (s.map (λa, b * f a)) = b * sum (s.map f) :=
id └─┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴└──┘ ┴
src └─┘ └──┘ ┴ ┴ ┴ └─┘ └──┘
typ └─┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴└──┘ ┴
doc └──┘ └──┘
784 multiset.induction_on s (by simp) (assume a s ih, by simp [ih, mul_add])
id └───────────────────┘ ┴ ┴ ┴ └┘ └┘ └─────┘
src └───────────────────┘ └──┘ └────┘ └┘└─────┘┴
typ └───────────────────┘ ┴ └──┘ ┴ ┴ └┘ └────┘└┘└┘└─────┘┴
doc └──┘ └────┘ └┘ ┴
txt └──┘ └────┘ └┘ ┴
par └──┘ └────┘ └┘ ┴
pid ┴┴ └┘ ┴
st └───┘ └─────────────────┘
785
786 lemma sum_map_mul_right [semiring β] {b : β} {s : multiset α} {f : α → β} :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘
787 sum (s.map (λa, f a * b)) = sum (s.map f) * b :=
id └─┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴└──┘ ┴ ┴ ┴
src └─┘ └──┘ ┴ ┴ └─┘ └──┘ ┴
typ └─┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴└──┘ ┴ ┴ ┴
doc └──┘ └──┘
788 multiset.induction_on s (by simp) (assume a s ih, by simp [ih, add_mul])
id └───────────────────┘ ┴ ┴ ┴ └┘ └┘ └─────┘
src └───────────────────┘ └──┘ └────┘ └┘└─────┘┴
typ └───────────────────┘ ┴ └──┘ ┴ ┴ └┘ └────┘└┘└┘└─────┘┴
doc └──┘ └────┘ └┘ ┴
txt └──┘ └────┘ └┘ ┴
par └──┘ └────┘ └┘ ┴
pid ┴┴ └┘ ┴
st └───┘ └─────────────────┘
789
790 @[to_additive]
doc └─────────┘
791 lemma prod_hom [comm_monoid α] [comm_monoid β] (s : multiset α) (f : α → β) [is_monoid_hom f] :
id └─────────┘ ┴ └─────────┘ ┴ └──────┘ ┴ ┴ ┴ └───────────┘ ┴
src └─────────┘ └─────────┘ └──────┘ └───────────┘
typ └─────────┘ ┴ └─────────┘ ┴ └──────┘ ┴ ┴ ┴ └───────────┘ ┴
doc └──────┘ └───────────┘
792 (s.map f).prod = f s.prod :=
id ┴└──┘ ┴ └──┘ ┴ ┴ ┴└───┘
src └──┘ └──┘ ┴ └───┘
typ ┴└──┘ ┴ └──┘ ┴ ┴ ┴└───┘
doc └──┘ └──┘ └───┘
793 quotient.induction_on s $ λ l, by simp only [l.prod_hom f, quot_mk_to_coe, coe_map, coe_prod]
id └───────────────────┘ ┴ ┴ └────────┘ ┴ └────────────┘ └─────┘ └──────┘
src └───────────────────┘ └─────────┘└────────┘┴ └┘└────────────┘└┘└─────┘└┘└──────┘└─
typ └───────────────────┘ ┴ ┴ └─────────┘└────────┘┴┴└┘└────────────┘└┘└─────┘└┘└──────┘└─
doc └─────────┘ ┴ └┘ └┘ └┘ └─
txt └─────────┘ ┴ └┘ └┘ └┘ └─
par └─────────┘ ┴ └┘ └┘ └┘ └─
pid ┴└──┘└┘ ┴ └┘ └┘ └┘ ┴└
st └────────────────────────────────────────────────────────────
794
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
795 @[to_additive]
doc └─────────┘
796 theorem prod_hom_rel [comm_monoid β] [comm_monoid γ] (s : multiset α) {r : β → γ → Prop}
id └─────────┘ ┴ └─────────┘ ┴ └──────┘ ┴ ┴ ┴
src └─────────┘ └─────────┘ └──────┘
typ └─────────┘ ┴ └─────────┘ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘
797 {f : α → β} {g : α → γ} (h₁ : r 1 1) (h₂ : ∀⦃a b c⦄, r b c → r (f a * b) (g a * c)) :
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
798 r (s.map f).prod (s.map g).prod :=
id ┴ ┴└──┘ ┴ └──┘ ┴└──┘ ┴ └──┘
src └──┘ └──┘ └──┘ └──┘
typ ┴ ┴└──┘ ┴ └──┘ ┴└──┘ ┴ └──┘
doc └──┘ └──┘ └──┘ └──┘
799 quotient.induction_on s $ λ l,
id └───────────────────┘ ┴ ┴
src └───────────────────┘
typ └───────────────────┘ ┴ ┴
800 by simp only [l.prod_hom_rel h₁ h₂, quot_mk_to_coe, coe_map, coe_prod]
id └────────────┘ └┘ └┘ └────────────┘ └─────┘ └──────┘
src └─────────┘└────────────┘┴ ┴ └┘└────────────┘└┘└─────┘└┘└──────┘└─
typ └─────────┘└────────────┘┴└┘┴└┘└┘└────────────┘└┘└─────┘└┘└──────┘└─
doc └─────────┘ ┴ ┴ └┘ └┘ └┘ └─
txt └─────────┘ ┴ ┴ └┘ └┘ └┘ └─
par └─────────┘ ┴ ┴ └┘ └┘ └┘ └─
pid ┴└──┘└┘ ┴ ┴ └┘ └┘ └┘ ┴└
st └────────────────────────────────────────────────────────────────────
801
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
802 lemma dvd_prod [comm_semiring α] {a : α} {s : multiset α} : a ∈ s → a ∣ s.prod :=
id └───────────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴└───┘
src └───────────┘ └──────┘ ┴ ┴ └───┘
typ └───────────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴└───┘
doc └──────┘ └───┘
803 quotient.induction_on s (λ l a h, by simpa using list.dvd_prod h) a
id └───────────────────┘ ┴ ┴ ┴ ┴ └───────────┘ ┴ ┴
src └───────────────────┘ └──────────┘└───────────┘┴
typ └───────────────────┘ ┴ ┴ ┴ ┴ └──────────┘└───────────┘┴┴ ┴
doc └──────────┘ ┴
txt └──────────┘ ┴
par └──────────┘ ┴
pid ┴└────┘ ┴
st └──────────────────────────┘
804
805 lemma le_sum_of_subadditive [add_comm_monoid α] [ordered_comm_monoid β]
id └─────────────┘ ┴ └─────────────────┘ ┴
src └─────────────┘ └─────────────────┘
typ └─────────────┘ ┴ └─────────────────┘ ┴
doc └─────────────────┘
806 (f : α → β) (h_zero : f 0 = 0) (h_add : ∀x y, f (x + y) ≤ f x + f y) (s : multiset α) :
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
src ┴ ┴ ┴ ┴ └──────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
807 f s.sum ≤ (s.map f).sum :=
id ┴ ┴└──┘ ┴ ┴└──┘ ┴ └─┘
src └──┘ ┴ └──┘ └─┘
typ ┴ ┴└──┘ ┴ ┴└──┘ ┴ └─┘
doc └──┘
808 multiset.induction_on s (le_of_eq h_zero) $
id └───────────────────┘ ┴ └──────┘ └────┘
src └───────────────────┘ └──────┘
typ └───────────────────┘ ┴ └──────┘ └────┘
809 assume a s ih, by rw [sum_cons, map_cons, sum_cons];
id ┴ ┴ └┘ └──────┘ └──────┘ └──────┘
src └──┘└──────┘└┘└──────┘└┘└──────┘┴
typ ┴ ┴ └┘ └──┘└──────┘└┘└──────┘└┘└──────┘┴
doc └──┘ └┘ └┘ ┴
txt └──┘ └┘ └┘ ┴
par └──┘ └┘ └┘ ┴
pid └┘ └┘ └┘ ┴
st └───────────┘└────────┘└────────┘┴└─
810 from le_trans (h_add a s.sum) (add_le_add_left' ih)
id └──────┘ └───┘ ┴ └───┘ └──────────────┘ └┘
src └───┘└──────┘┴ ┴ ┴└───┘└┘ └──────────────┘┴ └─
typ └───┘└──────┘┴ └───┘┴┴┴└───┘└┘ └──────────────┘┴└┘└─
doc └───┘ ┴ ┴ ┴ └┘ ┴ └─
txt └───┘ ┴ ┴ ┴ └┘ ┴ └─
par └───┘ ┴ ┴ ┴ └┘ ┴ └─
pid └───┘ ┴ ┴ ┴ └┘ ┴ ┴└
st ────────────────────────────────────────────────────────
811
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
812 lemma abs_sum_le_sum_abs [discrete_linear_ordered_field α] {s : multiset α} :
id └───────────────────────────┘ ┴ └──────┘ ┴
src └───────────────────────────┘ └──────┘
typ └───────────────────────────┘ ┴ └──────┘ ┴
doc └──────┘
813 abs s.sum ≤ (s.map abs).sum :=
id └─┘ ┴└──┘ ┴ ┴└──┘ └─┘ └─┘
src └─┘ └──┘ ┴ └──┘ └─┘ └─┘
typ └─┘ ┴└──┘ ┴ ┴└──┘ └─┘ └─┘
doc └──┘
814 le_sum_of_subadditive _ abs_zero abs_add s
id └───────────────────┘ └──────┘ └─────┘ ┴
src └───────────────────┘ └──────┘ └─────┘
typ └───────────────────┘ └──────┘ └─────┘ ┴
815
816 theorem dvd_sum [comm_semiring α] {a : α} {s : multiset α} : (∀ x ∈ s, a ∣ x) → a ∣ s.sum :=
id └───────────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└──┘
src └───────────┘ └──────┘ ┴ ┴ └──┘
typ └───────────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└──┘
doc └──────┘
817 multiset.induction_on s (λ _, dvd_zero _)
id └───────────────────┘ ┴ ┴ └──────┘
src └───────────────────┘ └──────┘
typ └───────────────────┘ ┴ ┴ └──────┘
818 (λ x s ih h, by rw sum_cons; exact dvd_add
id ┴ ┴ └┘ ┴ └──────┘ └─────┘
src └─┘└──────┘ └────┘└─────┘└
typ ┴ ┴ └┘ ┴ └─┘└──────┘ └────┘└─────┘└
doc └─┘ └────┘ └
txt └─┘ └────┘ └
par └─┘ └────┘ └
pid ┴ ┴ └
st └───────────────────────────
819 (h _ (mem_cons_self _ _)) (ih (λ y hy, h _ (mem_cons.2 (or.inr hy)))))
id └───────────┘ └┘ ┴ └──────┘ └────┘
src ───┘ └─┘ └───────────┘└─────┘ ┴ └─────┘ └─┘ └──────┘└─┘ └────┘┴ └──┘
typ ───┘ └─┘ └───────────┘└─────┘ └┘┴ └─────┘┴└─┘ └──────┘└─┘ └────┘┴ └──┘
doc ───┘ └─┘ └─────┘ ┴ └─────┘ └─┘ └─┘ ┴ └──┘
txt ───┘ └─┘ └─────┘ ┴ └─────┘ └─┘ └─┘ ┴ └──┘
par ───┘ └─┘ └─────┘ ┴ └─────┘ └─┘ └─┘ ┴ └──┘
pid ───┘ └─┘ └─────┘ ┴ └─────┘ └─┘ └─┘ ┴ └──┘
st ────────────────────────────────────────────────────────────────────────┘
820
821 /- join -/
822
823 /-- `join S`, where `S` is a multiset of multisets, is the lift of the list join
824 operation, that is, the union of all the sets.
825
826 join {{1, 2}, {1, 2}, {0, 1}} = {0, 1, 1, 1, 2, 2} -/
827 def join : multiset (multiset α) → multiset α := sum
id └──────┘ └──────┘ ┴ └──────┘ ┴ └─┘
src └──────┘ └──────┘ └──────┘ └─┘
typ └──────┘ └──────┘ ┴ └──────┘ ┴ └─┘
doc └──────┘ └──────┘ └──────┘
828
829 theorem coe_join : ∀ L : list (list α),
id ┴ └──┘ └──┘ ┴
src └──┘ └──┘
typ ┴ └──┘ └──┘ ┴
830 join (L.map (@coe _ (multiset α) _) : multiset (multiset α)) = L.join
id └──┘ ┴└──┘ └─┘ └──────┘ ┴ └──────┘ └──────┘ ┴ ┴ ┴└───┘
src └──┘ └──┘ └─┘ └──────┘ └──────┘ └──────┘ ┴ └───┘
typ └──┘ ┴└──┘ └─┘ └──────┘ ┴ └──────┘ └──────┘ ┴ ┴ ┴└───┘
doc └──┘ └──────┘ └──────┘ └──────┘
831 | [] := rfl
id └┘ └─┘
src └┘ └─┘
typ └┘ └─┘
832 | (l :: L) := congr_arg (λ s : multiset α, ↑l + s) (coe_join L)
id ┴ └┘ ┴ └───────┘ └──────┘ ┴ ┴ ┴ ┴ └──────┘
src └┘ └───────┘ └──────┘ ┴ ┴
typ ┴ └┘ ┴ └───────┘ └──────┘ ┴ ┴ ┴ ┴ └──────┘
doc └──────┘
833
834 @[simp] theorem join_zero : @join α 0 = 0 := rfl
id └──┘ ┴ ┴ └─┘
src └──┘ ┴ └─┘
typ └──┘ ┴ ┴ └─┘
doc └──┘ └──┘
835
836 @[simp] theorem join_cons (s S) : @join α (s :: S) = s + join S :=
id └──┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └──┘ ┴
src └──┘ └┘ ┴ ┴ └──┘
typ └──┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └──┘ ┴
doc └──┘ └──┘ └┘ └──┘
837 sum_cons _ _
id └──────┘
src └──────┘
typ └──────┘
838
839 @[simp] theorem join_add (S T) : @join α (S + T) = join S + join T :=
id └──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
src └──┘ ┴ ┴ └──┘ ┴ └──┘
typ └──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
doc └──┘ └──┘ └──┘ └──┘
840 sum_add _ _
id └─────┘
src └─────┘
typ └─────┘
841
842 @[simp] theorem mem_join {a S} : a ∈ @join α S ↔ ∃ s ∈ S, a ∈ s :=
id ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
src ┴ └──┘ ┴ ┴ ┴ ┴
typ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
doc └──┘ └──┘
843 multiset.induction_on S (by simp) $
id └───────────────────┘ ┴
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
844 by simp [or_and_distrib_right, exists_or_distrib] {contextual := tt}
id └──────────────────┘ └───────────────┘ └┘
src └────┘└──────────────────┘└┘└───────────────┘└┘ └────────────┘└┘└─
typ └────┘└──────────────────┘└┘└───────────────┘└┘ └────────────┘└┘└─
doc └────┘ └┘ └┘ └────────────┘ └─
txt └────┘ └┘ └┘ └────────────┘ └─
par └────┘ └┘ └┘ └────────────┘ └─
pid ┴┴ └┘ ┴┴ └────────────┘ ┴└
st └──────────────────────────────────────────────────────────────────
845
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
846 @[simp] theorem card_join (S) : card (@join α S) = sum (map card S) :=
id └──┘ └──┘ ┴ ┴ ┴ └─┘ └─┘ └──┘ ┴
src └──┘ └──┘ ┴ └─┘ └─┘ └──┘
typ └──┘ └──┘ ┴ ┴ ┴ └─┘ └─┘ └──┘ ┴
doc └──┘ └──┘ └──┘ └─┘ └──┘
847 multiset.induction_on S (by simp) (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘ └──┘
typ └───────────────────┘ ┴ └──┘ └──┘
doc └──┘ └──┘
txt └──┘ └──┘
par └──┘ └──┘
st └───┘ └───┘
848
849 /- bind -/
850
851 /-- `bind s f` is the monad bind operation, defined as `join (map f s)`.
852 It is the union of `f a` as `a` ranges over `s`. -/
853 def bind (s : multiset α) (f : α → multiset β) : multiset β :=
id └──────┘ ┴ ┴ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘
854 join (map f s)
id └──┘ └─┘ ┴ ┴
src └──┘ └─┘
typ └──┘ └─┘ ┴ ┴
doc └──┘ └─┘
855
856 @[simp] theorem coe_bind (l : list α) (f : α → list β) :
id └──┘ ┴ ┴ └──┘ ┴
src └──┘ └──┘
typ └──┘ ┴ ┴ └──┘ ┴
doc └──┘
857 @bind α β l (λ a, f a) = l.bind f :=
id └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└───┘ ┴
src └──┘ ┴ └───┘
typ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└───┘ ┴
doc └──┘
858 by rw [list.bind, ← coe_join, list.map_map]; refl
id └───────┘ └──────┘ └──────────┘
src └──┘└───────┘└──┘└──────┘└┘└──────────┘┴ └────
typ └──┘└───────┘└──┘└──────┘└┘└──────────┘┴ └────
doc └──┘ └──┘ └┘ ┴ └────
txt └──┘ └──┘ └┘ ┴ └────
par └──┘ └──┘ └┘ ┴ └────
pid └┘ └──┘ └┘ ┴ └
st └────────────┘└──────────┘└────────────┘┴└──────
859
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
860 @[simp] theorem zero_bind (f : α → multiset β) : bind 0 f = 0 := rfl
id ┴ └──────┘ ┴ └──┘ ┴ ┴ └─┘
src └──────┘ └──┘ ┴ └─┘
typ ┴ └──────┘ ┴ └──┘ ┴ ┴ └─┘
doc └──┘ └──────┘ └──┘
861
862 @[simp] theorem cons_bind (a s) (f : α → multiset β) : bind (a::s) f = f a + bind s f :=
id ┴ └──────┘ ┴ └──┘ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
src └──────┘ └──┘ └┘ ┴ ┴ └──┘
typ ┴ └──────┘ ┴ └──┘ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
doc └──┘ └──────┘ └──┘ └┘ └──┘
863 by simp [bind]
id └──┘
src └────┘└──┘└─
typ └────┘└──┘└─
doc └────┘└──┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └────────────
864
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
865 @[simp] theorem add_bind (s t) (f : α → multiset β) : bind (s + t) f = bind s f + bind t f :=
id ┴ └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴
src └──────┘ └──┘ ┴ ┴ └──┘ ┴ └──┘
typ ┴ └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴
doc └──┘ └──────┘ └──┘ └──┘ └──┘
866 by simp [bind]
id └──┘
src └────┘└──┘└─
typ └────┘└──┘└─
doc └────┘└──┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └────────────
867
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
868 @[simp] theorem bind_zero (s : multiset α) : bind s (λa, 0 : α → multiset β) = 0 :=
id └──────┘ ┴ └──┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──┘ └──────┘ ┴
typ └──────┘ ┴ └──┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──┘ └──────┘
869 by simp [bind, -map_const, join]
id └──┘ └──┘
src └────┘└──┘└────────────┘└──┘└─
typ └────┘└──┘└────────────┘└──┘└─
doc └────┘└──┘└────────────┘└──┘└─
txt └────┘ └────────────┘ └─
par └────┘ └────────────┘ └─
pid ┴┴ └────────────┘ ┴└
st └──────────────────────────────
870
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
871 @[simp] theorem bind_add (s : multiset α) (f g : α → multiset β) :
id └──────┘ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
872 bind s (λa, f a + g a) = bind s f + bind s g :=
id └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴
src └──┘ ┴ ┴ └──┘ ┴ └──┘
typ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴
doc └──┘ └──┘ └──┘
873 by simp [bind, join]
id └──┘ └──┘
src └────┘└──┘└┘└──┘└─
typ └────┘└──┘└┘└──┘└─
doc └────┘└──┘└┘└──┘└─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └──────────────────
874
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
875 @[simp] theorem bind_cons (s : multiset α) (f : α → β) (g : α → multiset β) :
id └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
876 bind s (λa, f a :: g a) = map f s + bind s g :=
id └──┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └──┘ ┴ ┴
src └──┘ └┘ ┴ └─┘ ┴ └──┘
typ └──┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └──┘ ┴ ┴
doc └──┘ └┘ └─┘ └──┘
877 multiset.induction_on s (by simp) (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴
doc └──┘ └───┘ └────────────┘ ┴
txt └──┘ └───┘ └────────────┘ ┴
par └──┘ └───┘ └────────────┘ ┴
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────┘
878
879 @[simp] theorem mem_bind {b s} {f : α → multiset β} : b ∈ bind s f ↔ ∃ a ∈ s, b ∈ f a :=
id ┴ └──────┘ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──┘ ┴ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──┘
880 by simp [bind]; simp [-exists_and_distrib_right, exists_and_distrib_right.symm];
id └──┘
src └────┘└──┘┴ └───────────────────────────────┘ ┴
typ └────┘└──┘┴ └───────────────────────────────┘└───────────────────────────┘┴
doc └────┘└──┘┴ └───────────────────────────────┘ ┴
txt └────┘ ┴ └───────────────────────────────┘ ┴
par └────┘ ┴ └───────────────────────────────┘ ┴
pid ┴┴ ┴ ┴└──────────────────────────┘ ┴
st └──────────────────────────────────────────────────────────────────────────────
881 rw exists_swap; simp [and_assoc]
id └─────────┘ └───────┘
src └─┘└─────────┘ └────┘└───────┘└─
typ └─┘└─────────┘ └────┘└───────┘└─
doc └─┘ └────┘ └─
txt └─┘ └────┘ └─
par └─┘ └────┘ └─
pid ┴ ┴┴ ┴└
st ─────┘└─────────┘└──────────────────
882
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
883 @[simp] theorem card_bind (s) (f : α → multiset β) : card (bind s f) = sum (map (card ∘ f) s) :=
id ┴ └──────┘ ┴ └──┘ └──┘ ┴ ┴ ┴ └─┘ └─┘ └──┘ ┴ ┴ ┴
src └──────┘ └──┘ └──┘ ┴ └─┘ └─┘ └──┘ ┴
typ ┴ └──────┘ ┴ └──┘ └──┘ ┴ ┴ ┴ └─┘ └─┘ └──┘ ┴ ┴ ┴
doc └──┘ └──────┘ └──┘ └──┘ └─┘ └──┘
884 by simp [bind]
id └──┘
src └────┘└──┘└─
typ └────┘└──┘└─
doc └────┘└──┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └────────────
885
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
886 lemma bind_congr {f g : α → multiset β} {m : multiset α} : (∀a∈m, f a = g a) → bind m f = bind m g :=
id ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴
src └──────┘ └──────┘ ┴ └──┘ ┴ └──┘
typ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴
doc └──────┘ └──────┘ └──┘ └──┘
887 by simp [bind] {contextual := tt}
id └──┘ └┘
src └────┘└──┘└┘ └────────────┘└┘└─
typ └────┘└──┘└┘ └────────────┘└┘└─
doc └────┘└──┘└┘ └────────────┘ └─
txt └────┘ └┘ └────────────┘ └─
par └────┘ └┘ └────────────┘ └─
pid ┴┴ ┴┴ └────────────┘ ┴└
st └───────────────────────────────
888
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
889 lemma bind_hcongr {β' : Type*} {m : multiset α} {f : α → multiset β} {f' : α → multiset β'}
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ └┘
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ └┘
doc └──────┘ └──────┘ └──────┘
890 (h : β = β') (hf : ∀a∈m, f a == f' a) : bind m f == bind m f' :=
id ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘ └┘ ┴ └──┘ ┴ ┴ └┘ └──┘ ┴ └┘
src ┴ └┘ └──┘ └┘ └──┘
typ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘ └┘ ┴ └──┘ ┴ ┴ └┘ └──┘ ┴ └┘
doc └──┘ └──┘
891 begin subst h, simp at hf, simp [bind_congr hf] end
id ┴ └────────┘ └┘
src └────┘ └────────┘ └────┘└────────┘┴ └┘
typ └────┘┴ └────────┘ └────┘└────────┘┴└┘└┘
doc └────┘ └────────┘ └────┘ ┴ └┘
txt └────┘ └────────┘ └────┘ ┴ └┘
par └────┘ └────────┘ └────┘ ┴ └┘
pid ┴ ┴└───┘ ┴┴ ┴ ┴┴
st └───────────┘└──────────┘└─────────────────────┘└─┘
892
893 lemma map_bind (m : multiset α) (n : α → multiset β) (f : β → γ) :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘ └──────┘
894 map f (bind m n) = bind m (λa, map f (n a)) :=
id └─┘ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴ └─┘ ┴ ┴ ┴
src └─┘ └──┘ ┴ └──┘ └─┘
typ └─┘ ┴ └──┘ ┴ ┴ ┴ └──┘ ┴ ┴ └─┘ ┴ ┴ ┴
doc └─┘ └──┘ └──┘ └─┘
895 multiset.induction_on m (by simp) (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴
doc └──┘ └───┘ └────────────┘ ┴
txt └──┘ └───┘ └────────────┘ ┴
par └──┘ └───┘ └────────────┘ ┴
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────┘
896
897 lemma bind_map (m : multiset α) (n : β → multiset γ) (f : α → β) :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘ └──────┘
898 bind (map f m) n = bind m (λa, n (f a)) :=
id └──┘ └─┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴
src └──┘ └─┘ ┴ └──┘
typ └──┘ └─┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └─┘ └──┘
899 multiset.induction_on m (by simp) (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴
doc └──┘ └───┘ └────────────┘ ┴
txt └──┘ └───┘ └────────────┘ ┴
par └──┘ └───┘ └────────────┘ ┴
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────┘
900
901 lemma bind_assoc {s : multiset α} {f : α → multiset β} {g : β → multiset γ} :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘
902 (s.bind f).bind g = s.bind (λa, (f a).bind g) :=
id ┴└───┘ ┴ └──┘ ┴ ┴ ┴└───┘ ┴ ┴ ┴ └──┘ ┴
src └───┘ └──┘ ┴ └───┘ └──┘
typ ┴└───┘ ┴ └──┘ ┴ ┴ ┴└───┘ ┴ ┴ ┴ └──┘ ┴
doc └───┘ └──┘ └───┘ └──┘
903 multiset.induction_on s (by simp) (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴
doc └──┘ └───┘ └────────────┘ ┴
txt └──┘ └───┘ └────────────┘ ┴
par └──┘ └───┘ └────────────┘ ┴
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────┘
904
905 lemma bind_bind (m : multiset α) (n : multiset β) {f : α → β → multiset γ} :
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘
906 (bind m $ λa, bind n $ λb, f a b) = (bind n $ λb, bind m $ λa, f a b) :=
id └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴
src └──┘ └──┘ ┴ └──┘ └──┘
typ └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──┘ └──┘ └──┘
907 multiset.induction_on m (by simp) (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴
doc └──┘ └───┘ └────────────┘ ┴
txt └──┘ └───┘ └────────────┘ ┴
par └──┘ └───┘ └────────────┘ ┴
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────┘
908
909 lemma bind_map_comm (m : multiset α) (n : multiset β) {f : α → β → γ} :
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘
910 (bind m $ λa, n.map $ λb, f a b) = (bind n $ λb, m.map $ λa, f a b) :=
id └──┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴
src └──┘ └──┘ ┴ └──┘ └──┘
typ └──┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴
doc └──┘ └──┘ └──┘ └──┘
911 multiset.induction_on m (by simp) (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴
doc └──┘ └───┘ └────────────┘ ┴
txt └──┘ └───┘ └────────────┘ ┴
par └──┘ └───┘ └────────────┘ ┴
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────┘
912
913 @[simp, to_additive]
doc └──┘ └─────────┘
914 lemma prod_bind [comm_monoid β] (s : multiset α) (t : α → multiset β) :
id └─────────┘ ┴ └──────┘ ┴ ┴ └──────┘ ┴
src └─────────┘ └──────┘ └──────┘
typ └─────────┘ ┴ └──────┘ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘
915 prod (bind s t) = prod (s.map $ λa, prod (t a)) :=
id └──┘ └──┘ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ └──┘ ┴ ┴
src └──┘ └──┘ ┴ └──┘ └──┘ └──┘
typ └──┘ └──┘ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ └──┘ ┴ ┴
doc └──┘ └──┘ └──┘ └──┘ └──┘
916 multiset.induction_on s (by simp) (assume a s ih, by simp [ih, cons_bind])
id └───────────────────┘ ┴ ┴ ┴ └┘ └┘ └───────┘
src └───────────────────┘ └──┘ └────┘ └┘└───────┘┴
typ └───────────────────┘ ┴ └──┘ ┴ ┴ └┘ └────┘└┘└┘└───────┘┴
doc └──┘ └────┘ └┘ ┴
txt └──┘ └────┘ └┘ ┴
par └──┘ └────┘ └┘ ┴
pid ┴┴ └┘ ┴
st └───┘ └───────────────────┘
917
918 /- product -/
919
920 /-- The multiplicity of `(a, b)` in `product s t` is
921 the product of the multiplicity of `a` in `s` and `b` in `t`. -/
922 def product (s : multiset α) (t : multiset β) : multiset (α × β) :=
id └──────┘ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴
src └──────┘ └──────┘ └──────┘ ┴
typ └──────┘ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘ └──────┘ └──────┘
923 s.bind $ λ a, t.map $ prod.mk a
id ┴└───┘ ┴ ┴└──┘ └─────┘ ┴
src └───┘ └──┘ └─────┘
typ ┴└───┘ ┴ ┴└──┘ └─────┘ ┴
doc └───┘ └──┘
924
925 @[simp] theorem coe_product (l₁ : list α) (l₂ : list β) :
id └──┘ ┴ └──┘ ┴
src └──┘ └──┘
typ └──┘ ┴ └──┘ ┴
doc └──┘
926 @product α β l₁ l₂ = l₁.product l₂ :=
id └─────┘ ┴ ┴ └┘ └┘ ┴ └┘└──────┘ └┘
src └─────┘ ┴ └──────┘
typ └─────┘ ┴ ┴ └┘ └┘ ┴ └┘└──────┘ └┘
doc └─────┘ └──────┘
927 by rw [product, list.product, ← coe_bind]; simp
id └─────┘ └──────────┘ └──────┘
src └──┘└─────┘└┘└──────────┘└──┘└──────┘┴ └────
typ └──┘└─────┘└┘└──────────┘└──┘└──────┘┴ └────
doc └──┘└─────┘└┘└──────────┘└──┘ ┴ └────
txt └──┘ └┘ └──┘ ┴ └────
par └──┘ └┘ └──┘ ┴ └────
pid └┘ └┘ └──┘ ┴ └
st └──────────┘└────────────┘└──────────┘┴└──────
928
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
929 @[simp] theorem zero_product (t) : @product α β 0 t = 0 := rfl
id └─────┘ ┴ ┴ ┴ ┴ └─┘
src └─────┘ ┴ └─┘
typ └─────┘ ┴ ┴ ┴ ┴ └─┘
doc └──┘ └─────┘
930
931 @[simp] theorem cons_product (a : α) (s : multiset α) (t : multiset β) :
id ┴ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ └──────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
932 product (a :: s) t = map (prod.mk a) t + product s t :=
id └─────┘ ┴ └┘ ┴ ┴ ┴ └─┘ └─────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
src └─────┘ └┘ ┴ └─┘ └─────┘ ┴ └─────┘
typ └─────┘ ┴ └┘ ┴ ┴ ┴ └─┘ └─────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
doc └─────┘ └┘ └─┘ └─────┘
933 by simp [product]
id └─────┘
src └────┘└─────┘└─
typ └────┘└─────┘└─
doc └────┘└─────┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └───────────────
934
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
935 @[simp] theorem product_singleton (a : α) (b : β) : product (a::0) (b::0) = (a,b)::0 := rfl
id ┴ ┴ └─────┘ ┴└┘ ┴└┘ ┴ ┴┴ ┴ └┘ └─┘
src └─────┘ └┘ └┘ ┴ ┴ └┘ └─┘
typ ┴ ┴ └─────┘ ┴└┘ ┴└┘ ┴ ┴┴ ┴ └┘ └─┘
doc └──┘ └─────┘ └┘ └┘ └┘
936
937 @[simp] theorem add_product (s t : multiset α) (u : multiset β) :
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
938 product (s + t) u = product s u + product t u :=
id └─────┘ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
src └─────┘ ┴ ┴ └─────┘ ┴ └─────┘
typ └─────┘ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
doc └─────┘ └─────┘ └─────┘
939 by simp [product]
id └─────┘
src └────┘└─────┘└─
typ └────┘└─────┘└─
doc └────┘└─────┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └───────────────
940
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
941 @[simp] theorem product_add (s : multiset α) : ∀ t u : multiset β,
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
942 product s (t + u) = product s t + product s u :=
id └─────┘ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
src └─────┘ ┴ ┴ └─────┘ ┴ └─────┘
typ └─────┘ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
doc └─────┘ └─────┘ └─────┘
943 multiset.induction_on s (λ t u, rfl) $ λ a s IH t u,
id └───────────────────┘ ┴ ┴ ┴ └─┘ ┴ ┴ └┘ ┴ ┴
src └───────────────────┘ └─┘
typ └───────────────────┘ ┴ ┴ ┴ └─┘ ┴ ┴ └┘ ┴ ┴
944 by rw [cons_product, IH]; simp
id └──────────┘ └┘
src └──┘└──────────┘└┘ ┴ └────
typ └──┘└──────────┘└┘└┘┴ └────
doc └──┘ └┘ ┴ └────
txt └──┘ └┘ ┴ └────
par └──┘ └┘ ┴ └────
pid └┘ └┘ ┴ └
st └───────────────┘└──┘┴└──────
945
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
946 @[simp] theorem mem_product {s t} : ∀ {p : α × β}, p ∈ @product α β s t ↔ p.1 ∈ s ∧ p.2 ∈ t
id ┴ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴
src ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴
doc └──┘ └─────┘
947 | (a, b) := by simp [product, and.left_comm]
id ┴ └─────┘ └───────────┘
src ┴ └────┘└─────┘└┘└───────────┘└─
typ ┴ └────┘└─────┘└┘└───────────┘└─
doc └────┘└─────┘└┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └──────────────────────────────
948
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
949 @[simp] theorem card_product (s : multiset α) (t : multiset β) : card (product s t) = card s * card t :=
id └──────┘ ┴ └──────┘ ┴ └──┘ └─────┘ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
src └──────┘ └──────┘ └──┘ └─────┘ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ └──────┘ ┴ └──┘ └─────┘ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
doc └──┘ └──────┘ └──────┘ └──┘ └─────┘ └──┘ └──┘
950 by simp [product, repeat, (∘), mul_comm]
id └─────┘ └────┘ ┴ └──────┘
src └────┘└─────┘└┘└────┘└┘┴└──┘└──────┘└─
typ └────┘└─────┘└┘└────┘└┘┴└──┘└──────┘└─
doc └────┘└─────┘└┘└────┘└┘ └──┘ └─
txt └────┘ └┘ └┘ └──┘ └─
par └────┘ └┘ └┘ └──┘ └─
pid ┴┴ └┘ └┘ └──┘ ┴└
st └──────────────────────────────────────
951
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
952 /- sigma -/
src ───────────┘
typ ───────────┘
doc ───────────┘
txt ───────────┘
par ───────────┘
pid ───────────┘
st ───────────┘
953 section
954 variable {σ : α → Type*}
955
956 /-- `sigma s t` is the dependent version of `product`. It is the sum of
957 `(a, b)` as `a` ranges over `s` and `b` ranges over `t a`. -/
958 protected def sigma (s : multiset α) (t : Π a, multiset (σ a)) : multiset (Σ a, σ a) :=
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴┴ ┴ ┴
src └──────┘ └──────┘ └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴┴ ┴ ┴
doc └──────┘ └──────┘ └──────┘
959 s.bind $ λ a, (t a).map $ sigma.mk a
id ┴└───┘ ┴ ┴ ┴ └─┘ └──────┘ ┴
src └───┘ └─┘ └──────┘
typ ┴└───┘ ┴ ┴ ┴ └─┘ └──────┘ ┴
doc └───┘ └─┘
960
961 @[simp] theorem coe_sigma (l₁ : list α) (l₂ : Π a, list (σ a)) :
id └──┘ ┴ ┴ └──┘ ┴ ┴
src └──┘ └──┘
typ └──┘ ┴ ┴ └──┘ ┴ ┴
doc └──┘
962 @multiset.sigma α σ l₁ (λ a, l₂ a) = l₁.sigma l₂ :=
id └────────────┘ ┴ ┴ └┘ ┴ └┘ ┴ ┴ └┘└────┘ └┘
src └────────────┘ ┴ └────┘
typ └────────────┘ ┴ ┴ └┘ ┴ └┘ ┴ ┴ └┘└────┘ └┘
doc └────────────┘ └────┘
963 by rw [multiset.sigma, list.sigma, ← coe_bind]; simp
id └────────────┘ └────────┘ └──────┘
src └──┘└────────────┘└┘└────────┘└──┘└──────┘┴ └────
typ └──┘└────────────┘└┘└────────┘└──┘└──────┘┴ └────
doc └──┘└────────────┘└┘└────────┘└──┘ ┴ └────
txt └──┘ └┘ └──┘ ┴ └────
par └──┘ └┘ └──┘ ┴ └────
pid └┘ └┘ └──┘ ┴ └
st └─────────────────┘└──────────┘└──────────┘┴└──────
964
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
965 @[simp] theorem zero_sigma (t) : @multiset.sigma α σ 0 t = 0 := rfl
id └────────────┘ ┴ ┴ ┴ ┴ └─┘
src └────────────┘ ┴ └─┘
typ └────────────┘ ┴ ┴ ┴ ┴ └─┘
doc └──┘ └────────────┘
966
967 @[simp] theorem cons_sigma (a : α) (s : multiset α) (t : Π a, multiset (σ a)) :
id ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘
968 (a :: s).sigma t = map (sigma.mk a) (t a) + s.sigma t :=
id ┴ └┘ ┴ └───┘ ┴ ┴ └─┘ └──────┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴
src └┘ └───┘ ┴ └─┘ └──────┘ ┴ └────┘
typ ┴ └┘ ┴ └───┘ ┴ ┴ └─┘ └──────┘ ┴ ┴ ┴ ┴ ┴└────┘ ┴
doc └┘ └───┘ └─┘ └────┘
969 by simp [multiset.sigma]
id └────────────┘
src └────┘└────────────┘└─
typ └────┘└────────────┘└─
doc └────┘└────────────┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └──────────────────────
970
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
971 @[simp] theorem sigma_singleton (a : α) (b : α → β) :
id ┴ ┴ ┴
typ ┴ ┴ ┴
doc └──┘
972 (a::0).sigma (λ a, b a::0) = ⟨a, b a⟩::0 := rfl
id ┴└┘ └───┘ ┴ ┴ ┴└┘ ┴ ┴ ┴ ┴ └┘ └─┘
src └┘ └───┘ └┘ ┴ └┘ └─┘
typ ┴└┘ └───┘ ┴ ┴ ┴└┘ ┴ ┴ ┴ ┴ └┘ └─┘
doc └┘ └───┘ └┘ └┘
973
974 @[simp] theorem add_sigma (s t : multiset α) (u : Π a, multiset (σ a)) :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘
975 (s + t).sigma u = s.sigma u + t.sigma u :=
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴└────┘ ┴
src ┴ └───┘ ┴ └────┘ ┴ └────┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴└────┘ ┴ ┴ ┴└────┘ ┴
doc └───┘ └────┘ └────┘
976 by simp [multiset.sigma]
id └────────────┘
src └────┘└────────────┘└─
typ └────┘└────────────┘└─
doc └────┘└────────────┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └──────────────────────
977
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
978 @[simp] theorem sigma_add (s : multiset α) : ∀ t u : Π a, multiset (σ a),
id └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘
979 s.sigma (λ a, t a + u a) = s.sigma t + s.sigma u :=
id ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴└────┘ ┴
src └────┘ ┴ ┴ └────┘ ┴ └────┘
typ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└────┘ ┴ ┴ ┴└────┘ ┴
doc └────┘ └────┘ └────┘
980 multiset.induction_on s (λ t u, rfl) $ λ a s IH t u,
id └───────────────────┘ ┴ ┴ ┴ └─┘ ┴ ┴ └┘ ┴ ┴
src └───────────────────┘ └─┘
typ └───────────────────┘ ┴ ┴ ┴ └─┘ ┴ ┴ └┘ ┴ ┴
981 by rw [cons_sigma, IH]; simp
id └────────┘ └┘
src └──┘└────────┘└┘ ┴ └────
typ └──┘└────────┘└┘└┘┴ └────
doc └──┘ └┘ ┴ └────
txt └──┘ └┘ ┴ └────
par └──┘ └┘ ┴ └────
pid └┘ └┘ ┴ └
st └─────────────┘└──┘┴└──────
982
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
983 @[simp] theorem mem_sigma {s t} : ∀ {p : Σ a, σ a},
id ┴ ┴ ┴┴ ┴ ┴
src ┴ ┴
typ ┴ ┴ ┴┴ ┴ ┴
doc └──┘
984 p ∈ @multiset.sigma α σ s t ↔ p.1 ∈ s ∧ p.2 ∈ t p.1
id ┴ ┴ └────────────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴┴
src ┴ └────────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ └────────────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴┴
doc └────────────┘
985 | ⟨a, b⟩ := by simp [multiset.sigma, and_assoc, and.left_comm]
id └────────────┘ └───────┘ └───────────┘
src └────┘└────────────┘└┘└───────┘└┘└───────────┘└─
typ └────┘└────────────┘└┘└───────┘└┘└───────────┘└─
doc └────┘└────────────┘└┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └────────────────────────────────────────────────
986
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
987 @[simp] theorem card_sigma (s : multiset α) (t : Π a, multiset (σ a)) :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘
988 card (s.sigma t) = sum (map (λ a, card (t a)) s) :=
id └──┘ ┴└────┘ ┴ ┴ └─┘ └─┘ ┴ └──┘ ┴ ┴ ┴
src └──┘ └────┘ ┴ └─┘ └─┘ └──┘
typ └──┘ ┴└────┘ ┴ ┴ └─┘ └─┘ ┴ └──┘ ┴ ┴ ┴
doc └──┘ └────┘ └─┘ └──┘
989 by simp [multiset.sigma, (∘)]
id └────────────┘ ┴
src └────┘└────────────┘└┘┴└───
typ └────┘└────────────┘└┘┴└───
doc └────┘└────────────┘└┘ └───
txt └────┘ └┘ └───
par └────┘ └┘ └───
pid ┴┴ └┘ └─┘└
st └───────────────────────────
990
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
991 end
992
993 /- map for partial functions -/
994
995 /-- Lift of the list `pmap` operation. Map a partial function `f` over a multiset
996 `s` whose elements are all in the domain of `f`. -/
997 def pmap {p : α → Prop} (f : Π a, p a → β) (s : multiset α) : (∀ a ∈ s, p a) → multiset β :=
id ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘
998 quot.rec_on s (λ l H, ↑(pmap f l H)) $ λ l₁ l₂ (pp : l₁ ~ l₂),
id └─────────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └┘
src └─────────┘ ┴ └──┘ ┴
typ └─────────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └┘
doc └──┘ ┴
999 funext $ λ (H₂ : ∀ a ∈ l₂, p a),
id └────┘ ┴ └┘ ┴ ┴
src └────┘
typ └────┘ ┴ └┘ ┴ ┴
1000 have H₁ : ∀ a ∈ l₁, p a, from λ a h, H₂ a ((mem_of_perm pp).1 h),
id ┴ └┘ ┴ ┴ ┴ ┴ └┘ ┴ └─────────┘ └┘ ┴ ┴
src └─────────┘ ┴
typ ┴ └┘ ┴ ┴ ┴ ┴ └┘ ┴ └─────────┘ └┘ ┴ ┴
1001 have ∀ {s₂ e H}, @eq.rec (multiset α) l₁
id └┘ ┴ ┴ └────┘ └──────┘ ┴ └┘
src └────┘ └──────┘
typ └┘ ┴ ┴ └────┘ └──────┘ ┴ └┘
doc └──────┘
1002 (λ s, (∀ a ∈ s, p a) → multiset β) (λ _, ↑(pmap f l₁ H₁))
id ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──┘ ┴ └┘ └┘
src └──────┘ ┴ └──┘
typ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──┘ ┴ └┘ └┘
doc └──────┘ └──┘
1003 s₂ e H = ↑(pmap f l₁ H₁), by intros s₂ e _; subst e,
id └┘ ┴ ┴ ┴ ┴ └──┘ ┴ └┘ └┘ ┴
src ┴ ┴ └──┘ └───────────┘ └────┘
typ └┘ ┴ ┴ ┴ ┴ └──┘ ┴ └┘ └┘ └───────────┘ └────┘┴
doc └──┘ └───────────┘ └────┘
txt └───────────┘ └────┘
par └───────────┘ └────┘
pid └─────┘ ┴
st └─────────────────────┘
1004 this.trans $ quot.sound $ perm_pmap f pp
id └──┘└────┘ └────────┘ └───────┘ ┴ └┘
src └────┘ └────────┘ └───────┘
typ └──┘└────┘ └────────┘ └───────┘ ┴ └┘
1005
1006 @[simp] theorem coe_pmap {p : α → Prop} (f : Π a, p a → β)
id ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴
doc └──┘
1007 (l : list α) (H : ∀ a ∈ l, p a) : pmap f l H = l.pmap f H := rfl
id └──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴└───┘ ┴ ┴ └─┘
src └──┘ └──┘ ┴ └───┘ └─┘
typ └──┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴└───┘ ┴ ┴ └─┘
doc └──┘ └───┘
1008
1009 @[simp] lemma pmap_zero {p : α → Prop} (f : Π a, p a → β) (h : ∀a∈(0:multiset α), p a) :
id ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴
src └──────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴
doc └──┘ └──────┘
1010 pmap f 0 h = 0 := rfl
id └──┘ ┴ ┴ ┴ └─┘
src └──┘ ┴ └─┘
typ └──┘ ┴ ┴ ┴ └─┘
doc └──┘
1011
1012 @[simp] lemma pmap_cons {p : α → Prop} (f : Π a, p a → β) (a : α) (m : multiset α) :
id ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘
1013 ∀(h : ∀b∈a::m, p b), pmap f (a :: m) h =
id ┴ ┴└┘┴ ┴ ┴ └──┘ ┴ ┴ └┘ ┴ ┴ ┴
src └┘ └──┘ └┘ ┴
typ ┴ ┴└┘┴ ┴ ┴ └──┘ ┴ ┴ └┘ ┴ ┴ ┴
doc └┘ └──┘ └┘
1014 f a (h a (mem_cons_self a m)) :: pmap f m (λa ha, h a $ mem_cons_of_mem ha) :=
id ┴ ┴ ┴ ┴ └───────────┘ ┴ ┴ └┘ └──┘ ┴ ┴ ┴ └┘ ┴ ┴ └─────────────┘ └┘
src └───────────┘ └┘ └──┘ └─────────────┘
typ ┴ ┴ ┴ ┴ └───────────┘ ┴ ┴ └┘ └──┘ ┴ ┴ ┴ └┘ ┴ ┴ └─────────────┘ └┘
doc └┘ └──┘
1015 quotient.induction_on m $ assume l h, rfl
id └───────────────────┘ ┴ ┴ ┴ └─┘
src └───────────────────┘ └─┘
typ └───────────────────┘ ┴ ┴ ┴ └─┘
1016
1017 /-- "Attach" a proof that `a ∈ s` to each element `a` in `s` to produce
1018 a multiset on `{x // x ∈ s}`. -/
1019 def attach (s : multiset α) : multiset {x // x ∈ s} := pmap subtype.mk s (λ a, id)
id └──────┘ ┴ └──────┘ ┴┴ ┴ ┴ ┴ └──┘ └────────┘ ┴ ┴ └┘
src └──────┘ └──────┘ ┴ ┴ └──┘ └────────┘ └┘
typ └──────┘ ┴ └──────┘ ┴┴ ┴ ┴ ┴ └──┘ └────────┘ ┴ ┴ └┘
doc └──────┘ └──────┘ └──┘
1020
1021 @[simp] theorem coe_attach (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
doc └──┘
1022 @eq (multiset {x // x ∈ l}) (@attach α l) l.attach := rfl
id └┘ └──────┘ ┴┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴└─────┘ └─┘
src └┘ └──────┘ ┴ ┴ └────┘ └─────┘ └─┘
typ └┘ └──────┘ ┴┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴└─────┘ └─┘
doc └──────┘ └────┘ └─────┘
1023
1024 theorem pmap_eq_map (p : α → Prop) (f : α → β) (s : multiset α) :
id ┴ ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
1025 ∀ H, @pmap _ _ p (λ a _, f a) s H = map f s :=
id ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
src └──┘ ┴ └─┘
typ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
doc └──┘ └─┘
1026 quot.induction_on s $ λ l H, congr_arg coe $ pmap_eq_map p f l H
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └─────────┘ ┴ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └─────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └─────────┘ ┴ ┴ ┴ ┴
1027
1028 theorem pmap_congr {p q : α → Prop} {f : Π a, p a → β} {g : Π a, q a → β}
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1029 (s : multiset α) {H₁ H₂} (h : ∀ a h₁ h₂, f a h₁ = g a h₂) :
id └──────┘ ┴ ┴ └┘ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
src └──────┘ ┴
typ └──────┘ ┴ ┴ └┘ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
doc └──────┘
1030 pmap f s H₁ = pmap g s H₂ :=
id └──┘ ┴ ┴ └┘ ┴ └──┘ ┴ ┴ └┘
src └──┘ ┴ └──┘
typ └──┘ ┴ ┴ └┘ ┴ └──┘ ┴ ┴ └┘
doc └──┘ └──┘
1031 quot.induction_on s (λ l H₁ H₂, congr_arg coe $ pmap_congr l h) H₁ H₂
id └───────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └────────┘ ┴ ┴ └┘ └┘
src └───────────────┘ └───────┘ └─┘ └────────┘
typ └───────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └────────┘ ┴ ┴ └┘ └┘
1032
1033 theorem map_pmap {p : α → Prop} (g : β → γ) (f : Π a, p a → β)
id ┴ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1034 (s) : ∀ H, map g (pmap f s H) = pmap (λ a h, g (f a h)) s H :=
id ┴ └─┘ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └─┘ └──┘ ┴ └──┘
typ ┴ └─┘ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └──┘ └──┘
1035 quot.induction_on s $ λ l H, congr_arg coe $ map_pmap g f l H
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └──────┘ ┴ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └──────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └──────┘ ┴ ┴ ┴ ┴
1036
1037 theorem pmap_eq_map_attach {p : α → Prop} (f : Π a, p a → β)
id ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴
1038 (s) : ∀ H, pmap f s H = s.attach.map (λ x, f x.1 (H _ x.2)) :=
id ┴ └──┘ ┴ ┴ ┴ ┴ ┴└─────┘└──┘ ┴ ┴ ┴┴ ┴ ┴┴
src └──┘ ┴ └─────┘└──┘ ┴ ┴
typ ┴ └──┘ ┴ ┴ ┴ ┴ ┴└─────┘└──┘ ┴ ┴ ┴┴ ┴ ┴┴
doc └──┘ └─────┘└──┘
1039 quot.induction_on s $ λ l H, congr_arg coe $ pmap_eq_map_attach f l H
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └────────────────┘ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └────────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └────────────────┘ ┴ ┴ ┴
1040
1041 theorem attach_map_val (s : multiset α) : s.attach.map subtype.val = s :=
id └──────┘ ┴ ┴└─────┘└──┘ └─────────┘ ┴ ┴
src └──────┘ └─────┘└──┘ └─────────┘ ┴
typ └──────┘ ┴ ┴└─────┘└──┘ └─────────┘ ┴ ┴
doc └──────┘ └─────┘└──┘
1042 quot.induction_on s $ λ l, congr_arg coe $ attach_map_val l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └────────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └────────────┘ ┴
1043
1044 @[simp] theorem mem_attach (s : multiset α) : ∀ x, x ∈ s.attach :=
id └──────┘ ┴ ┴ ┴ ┴ ┴└─────┘
src └──────┘ ┴ └─────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴└─────┘
doc └──┘ └──────┘ └─────┘
1045 quot.induction_on s $ λ l, mem_attach _
id └───────────────┘ ┴ ┴ └────────┘
src └───────────────┘ └────────┘
typ └───────────────┘ ┴ ┴ └────────┘
1046
1047 @[simp] theorem mem_pmap {p : α → Prop} {f : Π a, p a → β}
id ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴
doc └──┘
1048 {s H b} : b ∈ pmap f s H ↔ ∃ a (h : a ∈ s), f a (H a h) = b :=
id ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └──┘ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘
1049 quot.induction_on s (λ l H, mem_pmap) H
id └───────────────┘ ┴ ┴ ┴ └──────┘ ┴
src └───────────────┘ └──────┘
typ └───────────────┘ ┴ ┴ ┴ └──────┘ ┴
1050
1051 @[simp] theorem card_pmap {p : α → Prop} (f : Π a, p a → β)
id ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴
doc └──┘
1052 (s H) : card (pmap f s H) = card s :=
id └──┘ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴
src └──┘ └──┘ ┴ └──┘
typ └──┘ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴
doc └──┘ └──┘ └──┘
1053 quot.induction_on s (λ l H, length_pmap) H
id └───────────────┘ ┴ ┴ ┴ └─────────┘ ┴
src └───────────────┘ └─────────┘
typ └───────────────┘ ┴ ┴ ┴ └─────────┘ ┴
1054
1055 @[simp] theorem card_attach {m : multiset α} : card (attach m) = card m := card_pmap _ _ _
id └──────┘ ┴ └──┘ └────┘ ┴ ┴ └──┘ ┴ └───────┘
src └──────┘ └──┘ └────┘ ┴ └──┘ └───────┘
typ └──────┘ ┴ └──┘ └────┘ ┴ ┴ └──┘ ┴ └───────┘
doc └──┘ └──────┘ └──┘ └────┘ └──┘
1056
1057 @[simp] lemma attach_zero : (0 : multiset α).attach = 0 := rfl
id └──────┘ ┴ └────┘ ┴ └─┘
src └──────┘ └────┘ ┴ └─┘
typ └──────┘ ┴ └────┘ ┴ └─┘
doc └──┘ └──────┘ └────┘
1058
1059 lemma attach_cons (a : α) (m : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──────┘
1060 (a :: m).attach = ⟨a, mem_cons_self a m⟩ :: (m.attach.map $ λp, ⟨p.1, mem_cons_of_mem p.2⟩) :=
id ┴ └┘ ┴ └────┘ ┴ ┴ └───────────┘ ┴ ┴ └┘ ┴└─────┘└──┘ ┴ ┴┴ └─────────────┘ ┴┴
src └┘ └────┘ ┴ └───────────┘ └┘ └─────┘└──┘ ┴ └─────────────┘ ┴
typ ┴ └┘ ┴ └────┘ ┴ ┴ └───────────┘ ┴ ┴ └┘ ┴└─────┘└──┘ ┴ ┴┴ └─────────────┘ ┴┴
doc └┘ └────┘ └┘ └─────┘└──┘
1061 quotient.induction_on m $ assume l, congr_arg coe $ congr_arg (list.cons _) $
id └───────────────────┘ ┴ ┴ └───────┘ └─┘ └───────┘ └───────┘
src └───────────────────┘ └───────┘ └─┘ └───────┘ └───────┘
typ └───────────────────┘ ┴ ┴ └───────┘ └─┘ └───────┘ └───────┘
1062 by rw [list.map_pmap]; exact list.pmap_congr _ (assume a' h₁ h₂, subtype.eq rfl)
id └───────────┘ └─────────────┘ └────────┘ └─┘
src └──┘└───────────┘┴ └────┘└─────────────┘└─┘ └─────────┘└────────┘┴└─┘└─
typ └──┘└───────────┘┴ └────┘└─────────────┘└─┘ └─────────┘└────────┘┴└─┘└─
doc └──┘ ┴ └────┘ └─┘ └─────────┘ ┴ └─
txt └──┘ ┴ └────┘ └─┘ └─────────┘ ┴ └─
par └──┘ ┴ └────┘ └─┘ └─────────┘ ┴ └─
pid └┘ ┴ ┴ └─┘ └─────────┘ ┴ ┴└
st └────────────────┘┴└───────────────────────────────────────────────────────────
1063
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1064 section decidable_pi_exists
1065 variables {m : multiset α}
id └──────┘
src └──────┘
typ └──────┘
doc └──────┘
1066
1067 protected def decidable_forall_multiset {p : α → Prop} [hp : ∀a, decidable (p a)] :
id ┴ ┴ └───────┘ ┴ ┴
src └───────┘
typ ┴ ┴ └───────┘ ┴ ┴
1068 decidable (∀a∈m, p a) :=
id └───────┘ ┴ ┴ ┴ ┴
src └───────┘
typ └───────┘ ┴ ┴ ┴ ┴
1069 quotient.rec_on_subsingleton m (λl, decidable_of_iff (∀a∈l, p a) $ by simp)
id └──────────────────────────┘ ┴ ┴ └──────────────┘ ┴ ┴ ┴ ┴
src └──────────────────────────┘ └──────────────┘ └──┘
typ └──────────────────────────┘ ┴ ┴ └──────────────┘ ┴ ┴ ┴ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
1070
1071 instance decidable_dforall_multiset {p : Πa∈m, Prop} [hp : ∀a (h : a ∈ m), decidable (p a h)] :
id ┴ ┴ ┴ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴
src ┴ └───────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴
1072 decidable (∀a (h : a ∈ m), p a h) :=
id └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └───────┘ ┴
typ └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1073 decidable_of_decidable_of_iff
id └───────────────────────────┘
src └───────────────────────────┘
typ └───────────────────────────┘
1074 (@multiset.decidable_forall_multiset {a // a ∈ m} m.attach (λa, p a.1 a.2) _)
id └────────────────────────────────┘ ┴┴ ┴ ┴ ┴ ┴└─────┘ ┴ ┴ ┴┴ ┴┴
src └────────────────────────────────┘ ┴ ┴ └─────┘ ┴ ┴
typ └────────────────────────────────┘ ┴┴ ┴ ┴ ┴ ┴└─────┘ ┴ ┴ ┴┴ ┴┴
doc └─────┘
1075 (iff.intro (assume h a ha, h ⟨a, ha⟩ (mem_attach _ _)) (assume h ⟨a, ha⟩ _, h _ _))
id └───────┘ ┴ ┴ └┘ ┴ ┴ └┘ └────────┘ ┴ ┴ ┴ ┴
src └───────┘ └────────┘
typ └───────┘ ┴ ┴ └┘ ┴ ┴ └┘ └────────┘ ┴ ┴ ┴ ┴
1076
1077 /-- decidable equality for functions whose domain is bounded by multisets -/
1078 instance decidable_eq_pi_multiset {β : α → Type*} [h : ∀a, decidable_eq (β a)] :
id ┴ ┴ └──────────┘ ┴ ┴
src └──────────┘
typ ┴ ┴ └──────────┘ ┴ ┴
1079 decidable_eq (Πa∈m, β a) :=
id └──────────┘ ┴ ┴ ┴ ┴
src └──────────┘
typ └──────────┘ ┴ ┴ ┴ ┴
1080 assume f g, decidable_of_iff (∀a (h : a ∈ m), f a h = g a h) (by simp [function.funext_iff])
id ┴ ┴ └──────────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─────────────────┘
src └──────────────┘ ┴ ┴ └────┘└─────────────────┘┴
typ ┴ ┴ └──────────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘└─────────────────┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └─────────────────────────┘
1081
1082 def decidable_exists_multiset {p : α → Prop} [decidable_pred p] :
id ┴ └────────────┘ ┴
src └────────────┘
typ ┴ └────────────┘ ┴
1083 decidable (∃ x ∈ m, p x) :=
id └───────┘ ┴ ┴ ┴┴ ┴ ┴
src └───────┘ ┴ ┴
typ └───────┘ ┴ ┴ ┴┴ ┴ ┴
1084 quotient.rec_on_subsingleton m list.decidable_exists_mem
id └──────────────────────────┘ ┴ └───────────────────────┘
src └──────────────────────────┘ └───────────────────────┘
typ └──────────────────────────┘ ┴ └───────────────────────┘
1085
1086 instance decidable_dexists_multiset {p : Πa∈m, Prop} [hp : ∀a (h : a ∈ m), decidable (p a h)] :
id ┴ ┴ ┴ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴
src ┴ └───────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴
1087 decidable (∃a (h : a ∈ m), p a h) :=
id └───────┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └───────┘ ┴ ┴ ┴
typ └───────┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1088 decidable_of_decidable_of_iff
id └───────────────────────────┘
src └───────────────────────────┘
typ └───────────────────────────┘
1089 (@multiset.decidable_exists_multiset {a // a ∈ m} m.attach (λa, p a.1 a.2) _)
id └────────────────────────────────┘ ┴┴ ┴ ┴ ┴ ┴└─────┘ ┴ ┴ ┴┴ ┴┴
src └────────────────────────────────┘ ┴ ┴ └─────┘ ┴ ┴
typ └────────────────────────────────┘ ┴┴ ┴ ┴ ┴ ┴└─────┘ ┴ ┴ ┴┴ ┴┴
doc └─────┘
1090 (iff.intro (λ ⟨⟨a, ha₁⟩, _, ha₂⟩, ⟨a, ha₁, ha₂⟩)
id └───────┘ ┴ ┴ └─┘ └─┘
src └───────┘
typ └───────┘ ┴ ┴ └─┘ └─┘
1091 (λ ⟨a, ha₁, ha₂⟩, ⟨⟨a, ha₁⟩, mem_attach _ _, ha₂⟩))
id ┴┴ └─┘ └─┘ └────────┘
src └────────┘
typ ┴┴ └─┘ └─┘ └────────┘
1092
1093 end decidable_pi_exists
1094
1095 /- subtraction -/
1096 section
1097 variables [decidable_eq α] {s t u : multiset α} {a b : α}
id └──────────┘ └──────┘
src └──────────┘ └──────┘
typ └──────────┘ └──────┘
doc └──────┘
1098
1099 /-- `s - t` is the multiset such that
1100 `count a (s - t) = count a s - count a t` for all `a`. -/
1101 protected def sub (s t : multiset α) : multiset α :=
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
1102 quotient.lift_on₂ s t (λ l₁ l₂, (l₁.diff l₂ : multiset α)) $ λ v₁ v₂ w₁ w₂ p₁ p₂,
id └───────────────┘ ┴ ┴ └┘ └┘ └┘└───┘ └┘ └──────┘ ┴ └┘ └┘ └┘ └┘ └┘ └┘
src └───────────────┘ └───┘ └──────┘
typ └───────────────┘ ┴ ┴ └┘ └┘ └┘└───┘ └┘ └──────┘ ┴ └┘ └┘ └┘ └┘ └┘ └┘
doc └──────┘
1103 quot.sound $ perm_diff_right w₁ p₂ ▸ perm_diff_left _ p₁
id └────────┘ └─────────────┘ └┘ └┘ ┴ └────────────┘ └┘
src └────────┘ └─────────────┘ ┴ └────────────┘
typ └────────┘ └─────────────┘ └┘ └┘ ┴ └────────────┘ └┘
1104
1105 instance : has_sub (multiset α) := ⟨multiset.sub⟩
id └─────┘ └──────┘ ┴ └──────────┘
src └─────┘ └──────┘ └──────────┘
typ └─────┘ └──────┘ ┴ └──────────┘
doc └──────┘ └──────────┘
1106
1107 @[simp] theorem coe_sub (s t : list α) : (s - t : multiset α) = (s.diff t : list α) := rfl
id └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴└───┘ ┴ └──┘ ┴ └─┘
src └──┘ ┴ └──────┘ ┴ └───┘ └──┘ └─┘
typ └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴└───┘ ┴ └──┘ ┴ └─┘
doc └──┘ └──────┘
1108
1109 theorem sub_eq_fold_erase (s t : multiset α) : s - t = foldl erase erase_comm s t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └───┘ └───┘ └────────┘ ┴ ┴
src └──────┘ ┴ ┴ └───┘ └───┘ └────────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └───┘ └───┘ └────────┘ ┴ ┴
doc └──────┘ └───┘ └───┘
1110 quotient.induction_on₂ s t $ λ l₁ l₂,
id └────────────────────┘ ┴ ┴ └┘ └┘
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘
1111 show ↑(l₁.diff l₂) = foldl erase erase_comm ↑l₁ ↑l₂,
id ┴ └┘└───┘ └┘ ┴ └───┘ └───┘ └────────┘ ┴└┘ ┴└┘
src ┴ └───┘ ┴ └───┘ └───┘ └────────┘ ┴ ┴
typ ┴ └┘└───┘ └┘ ┴ └───┘ └───┘ └────────┘ ┴└┘ ┴└┘
doc └───┘ └───┘
1112 by { rw diff_eq_foldl l₁ l₂, symmetry, exact foldl_hom _ _ _ _ _ (λ x y, rfl) }
id └───────────┘ └┘ └┘ └───────┘ └─┘
src └─┘└───────────┘┴ ┴ └──────┘ └────┘└───────┘└─────────┘ └────┘└─┘└┘
typ └─┘└───────────┘┴└┘┴└┘ └──────┘ └────┘└───────┘└─────────┘ └────┘└─┘└┘
doc └─┘ ┴ ┴ └──────┘ └────┘ └─────────┘ └────┘ └┘
txt └─┘ ┴ ┴ └──────┘ └────┘ └─────────┘ └────┘ └┘
par └─┘ ┴ ┴ └──────┘ └────┘ └─────────┘ └────┘ └┘
pid ┴ ┴ ┴ ┴ └─────────┘ └────┘ ┴┴
st └───────────────────────┘└────────┘└───────────────────────────────────────┘└┘
1113
1114 @[simp] theorem sub_zero (s : multiset α) : s - 0 = s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
1115 quot.induction_on s $ λ l, rfl
id └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ └───────────────┘ ┴ ┴ └─┘
1116
1117 @[simp] theorem sub_cons (a : α) (s t : multiset α) : s - a::t = s.erase a - t :=
id ┴ └──────┘ ┴ ┴ ┴ ┴└┘┴ ┴ ┴└────┘ ┴ ┴ ┴
src └──────┘ ┴ └┘ ┴ └────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴└┘┴ ┴ ┴└────┘ ┴ ┴ ┴
doc └──┘ └──────┘ └┘ └────┘
1118 quotient.induction_on₂ s t $ λ l₁ l₂, congr_arg coe $ diff_cons _ _ _
id └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └───────┘
src └────────────────────┘ └───────┘ └─┘ └───────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └───────┘
1119
1120 theorem add_sub_of_le (h : s ≤ t) : s + (t - s) = t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1121 begin
st └─────
1122 revert t,
src └──────┘
typ └──────┘
doc └──────┘
txt └──────┘
par └──────┘
pid └┘
st ─────────┘└─
1123 refine multiset.induction_on s (by simp) (λ a s IH t h, _),
id └───────────────────┘ ┴
src └─────┘└───────────────────┘┴ ┴ ┴└──┘└┘ └─────────────┘
typ └─────┘└───────────────────┘┴┴┴ ┴└──┘└┘ └─────────────┘
doc └─────┘ ┴ ┴ ┴└──┘└┘ └─────────────┘
txt └─────┘ ┴ ┴ ┴└──┘└┘ └─────────────┘
par └─────┘ ┴ ┴ ┴└──┘└┘ └─────────────┘
pid ┴ ┴ ┴ └─────┘ └─────────────┘
st ───────────────────────────────────┘└───┘└─────────────────┘└─
1124 have := cons_erase (mem_of_le h (mem_cons_self _ _)),
id └────────┘ └───────┘ ┴ └───────────┘
src └──────┘└────────┘┴ └───────┘┴ ┴ └───────────┘└────┘
typ └──────┘└────────┘┴ └───────┘┴┴┴ └───────────┘└────┘
doc └──────┘ ┴ ┴ ┴ └────┘
txt └──────┘ ┴ ┴ ┴ └────┘
par └──────┘ ┴ ┴ ┴ └────┘
pid └───┘└─┘ ┴ ┴ ┴ └────┘
st ─────────────────────────────────────────────────────┘└─
1125 rw [cons_add, sub_cons, IH, this],
id └──────┘ └──────┘ └──┘
src └──┘└──────┘└┘└──────┘└┘ └┘ ┴
typ └──┘└──────┘└┘└──────┘└┘└┘└┘└──┘┴
doc └──┘ └┘ └┘ └┘ ┴
txt └──┘ └┘ └┘ └┘ ┴
par └──┘ └┘ └┘ └┘ ┴
pid └┘ └┘ └┘ └┘ ┴
st ─────────────┘└────────┘└──┘└────┘└──
1126 exact (cons_le_cons_iff a).1 (this.symm ▸ h)
id └──────────────┘ ┴ └───────┘ ┴ ┴
src └────┘ └──────────────┘┴ └──┘ └───────┘┴┴┴ └┘
typ └────┘ └──────────────┘┴┴└──┘ └───────┘┴┴┴┴└┘
doc └────┘ ┴ └──┘ ┴ ┴ └┘
txt └────┘ ┴ └──┘ ┴ ┴ └┘
par └────┘ ┴ └──┘ ┴ ┴ └┘
pid ┴ ┴ └──┘ ┴ ┴ ┴┴
st ──────────────────────────────────────────────┘
1127 end
st └─┘
1128
1129 theorem sub_add' : s - (t + u) = s - t - u :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1130 quotient.induction_on₃ s t u $
id └────────────────────┘ ┴ ┴ ┴
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ ┴
1131 λ l₁ l₂ l₃, congr_arg coe $ diff_append _ _ _
id └┘ └┘ └┘ └───────┘ └─┘ └─────────┘
src └───────┘ └─┘ └─────────┘
typ └┘ └┘ └┘ └───────┘ └─┘ └─────────┘
1132
1133 theorem sub_add_cancel (h : t ≤ s) : s - t + t = s :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1134 by rw [add_comm, add_sub_of_le h]
id └──────┘ └───────────┘ ┴
src └──┘└──────┘└┘└───────────┘┴ └─
typ └──┘└──────┘└┘└───────────┘┴┴└─
doc └──┘ └┘ ┴ └─
txt └──┘ └┘ ┴ └─
par └──┘ └┘ ┴ └─
pid └┘ └┘ ┴ ┴└
st └───────────┘└───────────────┘┴└
1135
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1136 @[simp] theorem add_sub_cancel_left (s : multiset α) : ∀ t, s + t - s = t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
1137 multiset.induction_on s (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
1138 (λ a s IH t, by rw [cons_add, sub_cons, erase_cons_head, IH])
id ┴ ┴ └┘ ┴ └──────┘ └──────┘ └─────────────┘ └┘
src └──┘└──────┘└┘└──────┘└┘└─────────────┘└┘ ┴
typ ┴ ┴ └┘ ┴ └──┘└──────┘└┘└──────┘└┘└─────────────┘└┘└┘┴
doc └──┘ └┘ └┘ └┘ ┴
txt └──┘ └┘ └┘ └┘ ┴
par └──┘ └┘ └┘ └┘ ┴
pid └┘ └┘ └┘ └┘ ┴
st └───────────┘└────────┘└───────────────┘└──┘┴
1139
1140 @[simp] theorem add_sub_cancel (s t : multiset α) : s + t - t = s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
1141 by rw [add_comm, add_sub_cancel_left]
id └──────┘ └─────────────────┘
src └──┘└──────┘└┘└─────────────────┘└─
typ └──┘└──────┘└┘└─────────────────┘└─
doc └──┘ └┘ └─
txt └──┘ └┘ └─
par └──┘ └┘ └─
pid └┘ └┘ ┴└
st └───────────┘└───────────────────┘┴└
1142
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1143 theorem sub_le_sub_right (h : s ≤ t) (u) : s - u ≤ t - u :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1144 by revert s t h; exact
src └──────────┘ └────┘
typ └──────────┘ └────┘
doc └──────────┘ └────┘
txt └──────────┘ └────┘
par └──────────┘ └────┘
pid └────┘ ┴
st └────────────────────
1145 multiset.induction_on u (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘┴ ┴ ┴└───┘ └────────────┘└┘┴└─
typ └───────────────────┘┴┴┴ ┴└───┘ └────────────┘└┘┴└─
doc ┴ ┴ ┴└───┘ └────────────┘ ┴└─
txt ┴ ┴ ┴└───┘ └────────────┘ ┴└─
par ┴ ┴ ┴└───┘ └────────────┘ ┴└─
pid ┴ ┴ └────┘ └────────────┘ └──
st ──────────────────────────┘└──────────────────────┘└─
1146 (λ a u IH s t h, by simp [IH, erase_le_erase a h])
id └────────────┘ ┴ ┴
src ─┘ └─────────────┘ ┴└────┘ └┘└────────────┘┴ ┴ ┴└─
typ ─┘ └─────────────┘ ┴└────┘└┘└┘└────────────┘┴┴┴┴┴└─
doc ─┘ └─────────────┘ ┴└────┘ └┘ ┴ ┴ ┴└─
txt ─┘ └─────────────┘ ┴└────┘ └┘ ┴ ┴ ┴└─
par ─┘ └─────────────┘ ┴└────┘ └┘ ┴ ┴ ┴└─
pid ─┘ └─────────────┘ └─────┘ └┘ ┴ ┴ └┘└
st ────────────────────┘└────────────────────────────┘└─
1147
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1148 theorem sub_le_sub_left (h : s ≤ t) : ∀ u, u - t ≤ u - s :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1149 le_induction_on h $ λ l₁ l₂ h, begin
id └─────────────┘ ┴ └┘ └┘ ┴
src └─────────────┘
typ └─────────────┘ ┴ └┘ └┘ ┴
st └─────
1150 induction h with l₁ l₂ a s IH l₁ l₂ a s IH; intro u,
id ┴
src └────────┘ └─────────────────────────────┘ └─────┘
typ └────────┘┴└─────────────────────────────┘ └─────┘
doc └────────┘ └─────────────────────────────┘ └─────┘
txt └────────┘ └─────────────────────────────┘ └─────┘
par └────────┘ └─────────────────────────────┘ └─────┘
pid ┴ ┴└────────────────────────────┘ └┘
st ────────────────────────────────────────────────────┘└─
1151 { refl },
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
pid ┴
st ───┘└───┘└┘└
1152 { rw [← cons_coe, sub_cons],
id └──────┘ └──────┘
src └────┘└──────┘└┘└──────┘┴
typ └────┘└──────┘└┘└──────┘┴
doc └────┘ └┘ ┴
txt └────┘ └┘ ┴
par └────┘ └┘ ┴
pid └──┘ └┘ ┴
st ───┘└────────────┘└────────┘┴└─
1153 exact le_trans (sub_le_sub_right (erase_le _ _) _) (IH u) },
id └──────┘ └──────────────┘ └──────┘ └┘ ┴
src └────┘└──────┘┴ └──────────────┘┴ └──────┘└───────┘ ┴ └┘
typ └────┘└──────┘┴ └──────────────┘┴ └──────┘└───────┘ └┘┴┴└┘
doc └────┘ ┴ ┴ └───────┘ ┴ └┘
txt └────┘ ┴ ┴ └───────┘ ┴ └┘
par └────┘ ┴ ┴ └───────┘ ┴ └┘
pid ┴ ┴ ┴ └───────┘ ┴ ┴┴
st ─────────────────────────────────────────────────────────────┘└┘└
1154 { rw [← cons_coe, sub_cons, ← cons_coe, sub_cons],
id └──────┘ └──────┘ └──────┘ └──────┘
src └────┘└──────┘└┘└──────┘└──┘└──────┘└┘└──────┘┴
typ └────┘└──────┘└┘└──────┘└──┘└──────┘└┘└──────┘┴
doc └────┘ └┘ └──┘ └┘ ┴
txt └────┘ └┘ └──┘ └┘ ┴
par └────┘ └┘ └──┘ └┘ ┴
pid └──┘ └┘ └──┘ └┘ ┴
st ─────────────────┘└────────┘└──────────┘└────────┘┴└─
1155 exact IH _ }
id └┘
src └────┘ └─┘
typ └────┘└┘└─┘
doc └────┘ └─┘
txt └────┘ └─┘
par └────┘ └─┘
pid ┴ └┘┴
st ──────────────┘└─
1156 end
st ──┘
1157
1158 theorem sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1159 by revert s; exact
src └──────┘ └────┘
typ └──────┘ └────┘
doc └──────┘ └────┘
txt └──────┘ └────┘
par └──────┘ └────┘
pid └┘ ┴
st └────────────────
1160 multiset.induction_on t (by simp)
id └───────────────────┘ ┴
src └───────────────────┘┴ ┴ ┴└──┘└─
typ └───────────────────┘┴┴┴ ┴└──┘└─
doc ┴ ┴ ┴└──┘└─
txt ┴ ┴ ┴└──┘└─
par ┴ ┴ ┴└──┘└─
pid ┴ ┴ └──────
st ──────────────────────────┘└───┘└─
1161 (λ a t IH s, by simp [IH, erase_le_iff_le_cons])
id └──────────────────┘
src ─┘ └─────────┘ ┴└────┘ └┘└──────────────────┘┴└─
typ ─┘ └─────────┘ ┴└────┘└┘└┘└──────────────────┘┴└─
doc ─┘ └─────────┘ ┴└────┘ └┘ ┴└─
txt ─┘ └─────────┘ ┴└────┘ └┘ ┴└─
par ─┘ └─────────┘ ┴└────┘ └┘ ┴└─
pid ─┘ └─────────┘ └─────┘ └┘ └┘└
st ────────────────┘└──────────────────────────────┘└─
1162
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1163 theorem le_sub_add (s t : multiset α) : s ≤ s - t + t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1164 sub_le_iff_le_add.1 (le_refl _)
id └───────────────┘┴ └─────┘
src └───────────────┘┴ └─────┘
typ └───────────────┘┴ └─────┘
1165
1166 theorem sub_le_self (s t : multiset α) : s - t ≤ s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1167 sub_le_iff_le_add.2 (le_add_right _ _)
id └───────────────┘┴ └──────────┘
src └───────────────┘┴ └──────────┘
typ └───────────────┘┴ └──────────┘
1168
1169 @[simp] theorem card_sub {s t : multiset α} (h : t ≤ s) : card (s - t) = card s - card t :=
id └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
src └──────┘ ┴ └──┘ ┴ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ └──┘ ┴
doc └──┘ └──────┘ └──┘ └──┘ └──┘
1170 (nat.sub_eq_of_eq_add $ by rw [add_comm, ← card_add, sub_add_cancel h]).symm
id └──────────────────┘ └──────┘ └──────┘ └────────────┘ ┴ └──┘
src └──────────────────┘ └──┘└──────┘└──┘└──────┘└┘└────────────┘┴ ┴ └──┘
typ └──────────────────┘ └──┘└──────┘└──┘└──────┘└┘└────────────┘┴┴┴ └──┘
doc └──┘ └──┘ └┘ ┴ ┴
txt └──┘ └──┘ └┘ ┴ ┴
par └──┘ └──┘ └┘ ┴ ┴
pid └┘ └──┘ └┘ ┴ ┴
st └───────────┘└──────────┘└────────────────┘┴
1171
1172 /- union -/
1173
1174 /-- `s ∪ t` is the lattice join operation with respect to the
1175 multiset `≤`. The multiplicity of `a` in `s ∪ t` is the maximum
1176 of the multiplicities in `s` and `t`. -/
1177 def union (s t : multiset α) : multiset α := s - t + t
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ ┴ ┴
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘
1178
1179 instance : has_union (multiset α) := ⟨union⟩
id └───────┘ └──────┘ ┴ └───┘
src └───────┘ └──────┘ └───┘
typ └───────┘ └──────┘ ┴ └───┘
doc └──────┘ └───┘
1180
1181 theorem union_def (s t : multiset α) : s ∪ t = s - t + t := rfl
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘
src └──────┘ ┴ ┴ ┴ ┴ └─┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘
doc └──────┘
1182
1183 theorem le_union_left (s t : multiset α) : s ≤ s ∪ t := le_sub_add _ _
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
src └──────┘ ┴ ┴ └────────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
doc └──────┘
1184
1185 theorem le_union_right (s t : multiset α) : t ≤ s ∪ t := le_add_left _ _
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └─────────┘
src └──────┘ ┴ ┴ └─────────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └─────────┘
doc └──────┘
1186
1187 theorem eq_union_left : t ≤ s → s ∪ t = s := sub_add_cancel
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────────────┘
src ┴ ┴ ┴ └────────────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────────────┘
1188
1189 theorem union_le_union_right (h : s ≤ t) (u) : s ∪ u ≤ t ∪ u :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1190 add_le_add_right (sub_le_sub_right h _) u
id └──────────────┘ └──────────────┘ ┴ ┴
src └──────────────┘ └──────────────┘
typ └──────────────┘ └──────────────┘ ┴ ┴
1191
1192 theorem union_le (h₁ : s ≤ u) (h₂ : t ≤ u) : s ∪ t ≤ u :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1193 by rw ← eq_union_left h₂; exact union_le_union_right h₁ t
id └───────────┘ └┘ └──────────────────┘ └┘ ┴
src └───┘└───────────┘┴ └────┘└──────────────────┘┴ ┴ └
typ └───┘└───────────┘┴└┘ └────┘└──────────────────┘┴└┘┴┴└
doc └───┘ ┴ └────┘ ┴ ┴ └
txt └───┘ ┴ └────┘ ┴ ┴ └
par └───┘ ┴ └────┘ ┴ ┴ └
pid └─┘ ┴ ┴ ┴ ┴ └
st └───────────────────────────────────────────────────────
1194
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1195 @[simp] theorem mem_union : a ∈ s ∪ t ↔ a ∈ s ∨ a ∈ t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘
1196 ⟨λ h, (mem_add.1 h).imp_left (mem_of_le $ sub_le_self _ _),
id ┴ └─────┘┴ ┴ └──────┘ └───────┘ └─────────┘
src └─────┘┴ └──────┘ └───────┘ └─────────┘
typ ┴ └─────┘┴ ┴ └──────┘ └───────┘ └─────────┘
1197 or.rec (mem_of_le $ le_union_left _ _) (mem_of_le $ le_union_right _ _)⟩
id └────┘ └───────┘ └───────────┘ └───────┘ └────────────┘
src └────┘ └───────┘ └───────────┘ └───────┘ └────────────┘
typ └────┘ └───────┘ └───────────┘ └───────┘ └────────────┘
1198
1199 @[simp] theorem map_union [decidable_eq β] {f : α → β} (finj : function.injective f) {s t : multiset α} :
id └──────────┘ ┴ ┴ ┴ └────────────────┘ ┴ └──────┘ ┴
src └──────────┘ └────────────────┘ └──────┘
typ └──────────┘ ┴ ┴ ┴ └────────────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
1200 map f (s ∪ t) = map f s ∪ map f t :=
id └─┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
src └─┘ ┴ ┴ └─┘ ┴ └─┘
typ └─┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
doc └─┘ └─┘ └─┘
1201 quotient.induction_on₂ s t $ λ l₁ l₂,
id └────────────────────┘ ┴ ┴ └┘ └┘
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘
1202 congr_arg coe (by rw [list.map_append f, list.map_diff finj])
id └───────┘ └─┘ └─────────────┘ ┴ └───────────┘ └──┘
src └───────┘ └─┘ └──┘└─────────────┘┴ └┘└───────────┘┴ ┴
typ └───────┘ └─┘ └──┘└─────────────┘┴┴└┘└───────────┘┴└──┘┴
doc └──┘ ┴ └┘ ┴ ┴
txt └──┘ ┴ └┘ ┴ ┴
par └──┘ ┴ └┘ ┴ ┴
pid └┘ ┴ └┘ ┴ ┴
st └────────────────────┘└──────────────────┘┴
1203
1204 /- inter -/
1205
1206 /-- `s ∩ t` is the lattice meet operation with respect to the
1207 multiset `≤`. The multiplicity of `a` in `s ∩ t` is the minimum
1208 of the multiplicities in `s` and `t`. -/
1209 def inter (s t : multiset α) : multiset α :=
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
1210 quotient.lift_on₂ s t (λ l₁ l₂, (l₁.bag_inter l₂ : multiset α)) $ λ v₁ v₂ w₁ w₂ p₁ p₂,
id └───────────────┘ ┴ ┴ └┘ └┘ └┘└────────┘ └┘ └──────┘ ┴ └┘ └┘ └┘ └┘ └┘ └┘
src └───────────────┘ └────────┘ └──────┘
typ └───────────────┘ ┴ ┴ └┘ └┘ └┘└────────┘ └┘ └──────┘ ┴ └┘ └┘ └┘ └┘ └┘ └┘
doc └──────┘
1211 quot.sound $ perm_bag_inter_right w₁ p₂ ▸ perm_bag_inter_left _ p₁
id └────────┘ └──────────────────┘ └┘ └┘ ┴ └─────────────────┘ └┘
src └────────┘ └──────────────────┘ ┴ └─────────────────┘
typ └────────┘ └──────────────────┘ └┘ └┘ ┴ └─────────────────┘ └┘
1212
1213 instance : has_inter (multiset α) := ⟨inter⟩
id └───────┘ └──────┘ ┴ └───┘
src └───────┘ └──────┘ └───┘
typ └───────┘ └──────┘ ┴ └───┘
doc └──────┘ └───┘
1214
1215 @[simp] theorem inter_zero (s : multiset α) : s ∩ 0 = 0 :=
id └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
1216 quot.induction_on s $ λ l, congr_arg coe l.bag_inter_nil
id └───────────────┘ ┴ ┴ └───────┘ └─┘ ┴└────────────┘
src └───────────────┘ └───────┘ └─┘ └────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ ┴└────────────┘
1217
1218 @[simp] theorem zero_inter (s : multiset α) : 0 ∩ s = 0 :=
id └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
1219 quot.induction_on s $ λ l, congr_arg coe l.nil_bag_inter
id └───────────────┘ ┴ ┴ └───────┘ └─┘ ┴└────────────┘
src └───────────────┘ └───────┘ └─┘ └────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ ┴└────────────┘
1220
1221 @[simp] theorem cons_inter_of_pos {a} (s : multiset α) {t} :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1222 a ∈ t → (a :: s) ∩ t = a :: s ∩ t.erase a :=
id ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴└────┘ ┴
src ┴ └┘ ┴ ┴ └┘ ┴ └────┘
typ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴└────┘ ┴
doc └┘ └┘ └────┘
1223 quotient.induction_on₂ s t $ λ l₁ l₂ h,
id └────────────────────┘ ┴ ┴ └┘ └┘ ┴
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ ┴
1224 congr_arg coe $ cons_bag_inter_of_pos _ h
id └───────┘ └─┘ └───────────────────┘ ┴
src └───────┘ └─┘ └───────────────────┘
typ └───────┘ └─┘ └───────────────────┘ ┴
1225
1226 @[simp] theorem cons_inter_of_neg {a} (s : multiset α) {t} :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1227 a ∉ t → (a :: s) ∩ t = s ∩ t :=
id ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └┘ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └┘
1228 quotient.induction_on₂ s t $ λ l₁ l₂ h,
id └────────────────────┘ ┴ ┴ └┘ └┘ ┴
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ ┴
1229 congr_arg coe $ cons_bag_inter_of_neg _ h
id └───────┘ └─┘ └───────────────────┘ ┴
src └───────┘ └─┘ └───────────────────┘
typ └───────┘ └─┘ └───────────────────┘ ┴
1230
1231 theorem inter_le_left (s t : multiset α) : s ∩ t ≤ s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1232 quotient.induction_on₂ s t $ λ l₁ l₂,
id └────────────────────┘ ┴ ┴ └┘ └┘
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘
1233 subperm_of_sublist $ bag_inter_sublist_left _ _
id └────────────────┘ └────────────────────┘
src └────────────────┘ └────────────────────┘
typ └────────────────┘ └────────────────────┘
1234
1235 theorem inter_le_right (s : multiset α) : ∀ t, s ∩ t ≤ t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1236 multiset.induction_on s (λ t, (zero_inter t).symm ▸ zero_le _) $
id └───────────────────┘ ┴ ┴ └────────┘ ┴ └──┘ ┴ └─────┘
src └───────────────────┘ └────────┘ └──┘ ┴ └─────┘
typ └───────────────────┘ ┴ ┴ └────────┘ ┴ └──┘ ┴ └─────┘
1237 λ a s IH t, if h : a ∈ t
id ┴ ┴ └┘ ┴ └┘ ┴ ┴ ┴
src └┘ ┴
typ ┴ ┴ └┘ ┴ └┘ ┴ ┴ ┴
1238 then by simpa [h] using cons_le_cons a (IH (t.erase a))
id ┴ └──────────┘ └┘ └─────┘ ┴
src └─────┘ └──────┘└──────────┘┴ ┴ ┴ └─────┘┴ └──
typ └─────┘┴└──────┘└──────────┘┴ ┴ └┘┴ └─────┘┴┴└──
doc └─────┘ └──────┘ ┴ ┴ ┴ └─────┘┴ └──
txt └─────┘ └──────┘ ┴ ┴ ┴ ┴ └──
par └─────┘ └──────┘ ┴ ┴ ┴ ┴ └──
pid ┴┴ ┴┴└────┘ ┴ ┴ ┴ ┴ └┘└
st └────────────────────────────────────────────────
1239 else by simp [h, IH]
id ┴ └┘
src ─┘ └────┘ └┘ └─
typ ─┘ └────┘┴└┘└┘└─
doc ─┘ └────┘ └┘ └─
txt ─┘ └────┘ └┘ └─
par ─┘ └────┘ └┘ └─
pid ─┘ ┴┴ └┘ ┴└
st ─┘ └─────────────
1240
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1241 theorem le_inter (h₁ : s ≤ t) (h₂ : s ≤ u) : s ≤ t ∩ u :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1242 begin
st └─────
1243 revert s u, refine multiset.induction_on t _ (λ a t IH, _); intros,
id └───────────────────┘ ┴
src └────────┘ └─────┘└───────────────────┘┴ └─┘ └─────────┘ └────┘
typ └────────┘ └─────┘└───────────────────┘┴┴└─┘ └─────────┘ └────┘
doc └────────┘ └─────┘ ┴ └─┘ └─────────┘ └────┘
txt └────────┘ └─────┘ ┴ └─┘ └─────────┘ └────┘
par └────────┘ └─────┘ ┴ └─┘ └─────────┘ └────┘
pid └──┘ ┴ ┴ └─┘ └─────────┘
st ───────────┘└──────────────────────────────────────────────────────┘└─
1244 { simp [h₁] },
id └┘
src └────┘ └┘
typ └────┘└┘└┘
doc └────┘ └┘
txt └────┘ └┘
par └────┘ └┘
pid ┴┴ ┴┴
st ───┘└────────┘└┘└
1245 by_cases a ∈ u,
id ┴ ┴ ┴
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────┘└─
1246 { rw [cons_inter_of_pos _ h, ← erase_le_iff_le_cons],
id └───────────────┘ ┴ └──────────────────┘
src └──┘└───────────────┘└─┘ └──┘└──────────────────┘┴
typ └──┘└───────────────┘└─┘┴└──┘└──────────────────┘┴
doc └──┘ └─┘ └──┘ ┴
txt └──┘ └─┘ └──┘ ┴
par └──┘ └─┘ └──┘ ┴
pid └┘ └─┘ └──┘ ┴
st ───┘└───────────────────────┘└──────────────────────┘└──
1247 exact IH (erase_le_iff_le_cons.2 h₁) (erase_le_erase _ h₂) },
id └┘ └──────────────────┘ └┘ └────────────┘ └┘
src └────┘ ┴ └──────────────────┘└─┘ └┘ └────────────┘└─┘ └┘
typ └────┘└┘┴ └──────────────────┘└─┘└┘└┘ └────────────┘└─┘└┘└┘
doc └────┘ ┴ └─┘ └┘ └─┘ └┘
txt └────┘ ┴ └─┘ └┘ └─┘ └┘
par └────┘ ┴ └─┘ └┘ └─┘ └┘
pid ┴ ┴ └─┘ └┘ └─┘ ┴┴
st ──────────────────────────────────────────────────────────────┘└┘└
1248 { rw cons_inter_of_neg _ h,
id └───────────────┘ ┴
src └─┘└───────────────┘└─┘
typ └─┘└───────────────┘└─┘┴
doc └─┘ └─┘
txt └─┘ └─┘
par └─┘ └─┘
pid ┴ └─┘
st ───────────────────────────┘└─
1249 exact IH ((le_cons_of_not_mem $ mt (mem_of_le h₂) h).1 h₁) h₂ }
id └┘ └────────────────┘ └┘ └───────┘ ┴ └┘ └┘
src └────┘ ┴ └────────────────┘┴ ┴└┘┴ └───────┘┴ └┘ └──┘ └┘ ┴
typ └────┘└┘┴ └────────────────┘┴ ┴└┘┴ └───────┘┴ └┘┴└──┘└┘└┘└┘┴
doc └────┘ ┴ ┴ ┴ ┴ ┴ └┘ └──┘ └┘ ┴
txt └────┘ ┴ ┴ ┴ ┴ ┴ └┘ └──┘ └┘ ┴
par └────┘ ┴ ┴ ┴ ┴ ┴ └┘ └──┘ └┘ ┴
pid ┴ ┴ ┴ ┴ ┴ ┴ └┘ └──┘ └┘ ┴
st ─────────────────────────────────────────────────────────────────┘└─
1250 end
st ──┘
1251
1252 @[simp] theorem mem_inter : a ∈ s ∩ t ↔ a ∈ s ∧ a ∈ t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘
1253 ⟨λ h, ⟨mem_of_le (inter_le_left _ _) h, mem_of_le (inter_le_right _ _) h⟩,
id ┴ └───────┘ └───────────┘ ┴ └───────┘ └────────────┘ ┴
src └───────┘ └───────────┘ └───────┘ └────────────┘
typ ┴ └───────┘ └───────────┘ ┴ └───────┘ └────────────┘ ┴
1254 λ ⟨h₁, h₂⟩, by rw [← cons_erase h₁, cons_inter_of_pos _ h₂]; apply mem_cons_self⟩
id ┴ └────────┘ └┘ └───────────────┘ └┘ └───────────┘
src └────┘└────────┘┴ └┘└───────────────┘└─┘ ┴ └────┘└───────────┘
typ ┴ └────┘└────────┘┴└┘└┘└───────────────┘└─┘└┘┴ └────┘└───────────┘
doc └────┘ ┴ └┘ └─┘ ┴ └────┘
txt └────┘ ┴ └┘ └─┘ ┴ └────┘
par └────┘ ┴ └┘ └─┘ ┴ └────┘
pid └──┘ ┴ └┘ └─┘ ┴ ┴
st └──────────────────┘└──────────────────────┘┴└───────────────────┘
1255
1256 instance : lattice (multiset α) :=
id └─────┘ └──────┘ ┴
src └─────┘ └──────┘
typ └─────┘ └──────┘ ┴
doc └─────┘ └──────┘
1257 { sup := (∪),
id ┴
src ┴
typ ┴
1258 sup_le := @union_le _ _,
id └──────┘
src └──────┘
typ └──────┘
1259 le_sup_left := le_union_left,
id └───────────┘
src └───────────┘
typ └───────────┘
1260 le_sup_right := le_union_right,
id └────────────┘
src └────────────┘
typ └────────────┘
1261 inf := (∩),
id ┴
src ┴
typ ┴
1262 le_inf := @le_inter _ _,
id └──────┘
src └──────┘
typ └──────┘
1263 inf_le_left := inter_le_left,
id └───────────┘
src └───────────┘
typ └───────────┘
1264 inf_le_right := inter_le_right,
id └────────────┘
src └────────────┘
typ └────────────┘
1265 ..@multiset.partial_order α }
id └────────────────────┘ ┴
src └────────────────────┘
typ └────────────────────┘ ┴
1266
1267 @[simp] theorem sup_eq_union (s t : multiset α) : s ⊔ t = s ∪ t := rfl
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘
src └──────┘ ┴ ┴ ┴ └─┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘
doc └──┘ └──────┘
1268 @[simp] theorem inf_eq_inter (s t : multiset α) : s ⊓ t = s ∩ t := rfl
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘
src └──────┘ ┴ ┴ ┴ └─┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘
doc └──┘ └──────┘
1269
1270 @[simp] theorem le_inter_iff : s ≤ t ∩ u ↔ s ≤ t ∧ s ≤ u := le_inf_iff
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
src ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
doc └──┘
1271 @[simp] theorem union_le_iff : s ∪ t ≤ u ↔ s ≤ u ∧ t ≤ u := sup_le_iff
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
src ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────────┘
doc └──┘
1272
1273 instance : semilattice_inf_bot (multiset α) :=
id └─────────────────┘ └──────┘ ┴
src └─────────────────┘ └──────┘
typ └─────────────────┘ └──────┘ ┴
doc └─────────────────┘ └──────┘
1274 { bot := 0, bot_le := zero_le, ..multiset.lattice.lattice }
id └─────┘ └──────────────────────┘
src └─────┘ └──────────────────────┘
typ └─────┘ └──────────────────────┘
1275
1276 theorem union_comm (s t : multiset α) : s ∪ t = t ∪ s := sup_comm
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘
src └──────┘ ┴ ┴ ┴ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘
doc └──────┘
1277 theorem inter_comm (s t : multiset α) : s ∩ t = t ∩ s := inf_comm
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘
src └──────┘ ┴ ┴ ┴ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘
doc └──────┘
1278
1279 theorem eq_union_right (h : s ≤ t) : s ∪ t = t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1280 by rw [union_comm, eq_union_left h]
id └────────┘ └───────────┘ ┴
src └──┘└────────┘└┘└───────────┘┴ └─
typ └──┘└────────┘└┘└───────────┘┴┴└─
doc └──┘ └┘ ┴ └─
txt └──┘ └┘ ┴ └─
par └──┘ └┘ ┴ └─
pid └┘ └┘ ┴ ┴└
st └─────────────┘└───────────────┘┴└
1281
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1282 theorem union_le_union_left (h : s ≤ t) (u) : u ∪ s ≤ u ∪ t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
1283 sup_le_sup_left h _
id └─────────────┘ ┴
src └─────────────┘
typ └─────────────┘ ┴
1284
1285 theorem union_le_add (s t : multiset α) : s ∪ t ≤ s + t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1286 union_le (le_add_right _ _) (le_add_left _ _)
id └──────┘ └──────────┘ └─────────┘
src └──────┘ └──────────┘ └─────────┘
typ └──────┘ └──────────┘ └─────────┘
1287
1288 theorem union_add_distrib (s t u : multiset α) : (s ∪ t) + u = (s + u) ∪ (t + u) :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1289 by simpa [(∪), union, eq_comm] using show s + u - (t + u) = s - t,
id └───┘ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └─────┘ └──┘└───┘└┘└─────┘└──────┘ ┴ ┴┴┴ ┴┴┴ ┴ ┴ └┘┴┴ ┴ ┴ └─
typ └─────┘ └──┘└───┘└┘└─────┘└──────┘ ┴ ┴┴┴ ┴┴┴ ┴ ┴┴└┘┴┴┴┴ ┴┴└─
doc └─────┘ └──┘└───┘└┘ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─
txt └─────┘ └──┘ └┘ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─
par └─────┘ └──┘ └┘ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─
pid ┴┴ └──┘ └┘ ┴┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─
st └────────────────────────────────────────────────────────────────
1290 by rw [add_comm t, sub_add', add_sub_cancel]
id └──────┘ ┴ └──────┘ └────────────┘
src ──┘└──┘└──────┘┴ └┘└──────┘└┘└────────────┘└─
typ ──┘└──┘└──────┘┴┴└┘└──────┘└┘└────────────┘└─
doc ──┘└──┘ ┴ └┘ └┘ └─
txt ──┘└──┘ ┴ └┘ └┘ └─
par ──┘└──┘ ┴ └┘ └┘ └─
pid ──────┘ ┴ └┘ └┘ └─
st ─┘└─────────────┘└────────┘└──────────────┘┴└
1291
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1292 theorem add_union_distrib (s t u : multiset α) : s + (t ∪ u) = (s + t) ∪ (s + u) :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1293 by rw [add_comm, union_add_distrib, add_comm s, add_comm s]
id └──────┘ └───────────────┘ └──────┘ ┴ └──────┘ ┴
src └──┘└──────┘└┘└───────────────┘└┘└──────┘┴ └┘└──────┘┴ └─
typ └──┘└──────┘└┘└───────────────┘└┘└──────┘┴┴└┘└──────┘┴┴└─
doc └──┘ └┘ └┘ ┴ └┘ ┴ └─
txt └──┘ └┘ └┘ ┴ └┘ ┴ └─
par └──┘ └┘ └┘ ┴ └┘ ┴ └─
pid └┘ └┘ └┘ ┴ └┘ ┴ ┴└
st └───────────┘└─────────────────┘└──────────┘└──────────┘┴└
1294
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1295 theorem cons_union_distrib (a : α) (s t : multiset α) : a :: (s ∪ t) = (a :: s) ∪ (a :: t) :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴
src └──────┘ └┘ ┴ ┴ └┘ ┴ └┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘ └┘ └┘
1296 by simpa using add_union_distrib (a::0) s t
id └───────────────┘ ┴└┘ ┴ ┴
src └──────────┘└───────────────┘┴ └┘└─┘ ┴ └
typ └──────────┘└───────────────┘┴ ┴└┘└─┘┴┴┴└
doc └──────────┘ ┴ └┘└─┘ ┴ └
txt └──────────┘ ┴ └─┘ ┴ └
par └──────────┘ ┴ └─┘ ┴ └
pid ┴└────┘ ┴ └─┘ ┴ └
st └─────────────────────────────────────────
1297
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1298 theorem inter_add_distrib (s t u : multiset α) : (s ∩ t) + u = (s + u) ∩ (t + u) :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1299 begin
st └─────
1300 by_contra h,
src └─────────┘
typ └─────────┘
doc └─────────┘
txt └─────────┘
par └─────────┘
pid └┘
st ────────────┘└─
1301 cases lt_iff_cons_le.1 (lt_of_le_of_ne (le_inter
id └────────────┘ └────────────┘ └──────┘
src └────┘└────────────┘└─┘ └────────────┘┴ └──────┘└
typ └────┘└────────────┘└─┘ └────────────┘┴ └──────┘└
doc └────┘ └─┘ ┴ └
txt └────┘ └─┘ ┴ └
par └────┘ └─┘ ┴ └
pid ┴ └─┘ ┴ └
st ───────────────────────────────────────────────────
1302 (add_le_add_right (inter_le_left s t) u)
id └───────────┘
src ───┘ ┴ └───────────┘┴ ┴ └┘ └─
typ ───┘ ┴ └───────────┘┴ ┴ └┘ └─
doc ───┘ ┴ ┴ ┴ └┘ └─
txt ───┘ ┴ ┴ ┴ └┘ └─
par ───┘ ┴ ┴ ┴ └┘ └─
pid ───┘ ┴ ┴ ┴ └┘ └─
st ─────────────────────────────────────────────
1303 (add_le_add_right (inter_le_right s t) u)) h) with a hl,
id └──────────────┘ └────────────┘ ┴ ┴ ┴ ┴
src ───┘ └──────────────┘┴ └────────────┘┴ ┴ └┘ └─┘ └─────────┘
typ ───┘ └──────────────┘┴ └────────────┘┴┴┴┴└┘┴└─┘┴└─────────┘
doc ───┘ ┴ ┴ ┴ └┘ └─┘ └─────────┘
txt ───┘ ┴ ┴ ┴ └┘ └─┘ └─────────┘
par ───┘ ┴ ┴ ┴ └┘ └─┘ └─────────┘
pid ───┘ ┴ ┴ ┴ └┘ └─┘ ┴└────────┘
st ──────────────────────────────────────────────────────────┘└─
1304 rw ← cons_add at hl,
id └──────┘
src └───┘└──────┘└────┘
typ └───┘└──────┘└────┘
doc └───┘ └────┘
txt └───┘ └────┘
par └───┘ └────┘
pid └─┘ └────┘
st ────────────────────┘└─
1305 exact not_le_of_lt (lt_cons_self (s ∩ t) a) (le_inter
id └──────────┘ └──────────┘ ┴ ┴ ┴ ┴ └──────┘
src └────┘└──────────┘┴ └──────────┘┴ ┴┴┴ └┘ └┘ └──────┘└
typ └────┘└──────────┘┴ └──────────┘┴ ┴┴┴┴┴└┘┴└┘ └──────┘└
doc └────┘ ┴ ┴ ┴ ┴ └┘ └┘ └
txt └────┘ ┴ ┴ ┴ ┴ └┘ └┘ └
par └────┘ ┴ ┴ ┴ ┴ └┘ └┘ └
pid ┴ ┴ ┴ ┴ ┴ └┘ └┘ └
st ────────────────────────────────────────────────────────
1306 (le_of_add_le_add_right (le_trans hl (inter_le_left _ _)))
id └───────────┘
src ───┘ ┴ ┴ ┴ └───────────┘└───────
typ ───┘ ┴ ┴ ┴ └───────────┘└───────
doc ───┘ ┴ ┴ ┴ └───────
txt ───┘ ┴ ┴ ┴ └───────
par ───┘ ┴ ┴ ┴ └───────
pid ───┘ ┴ ┴ ┴ └───────
st ───────────────────────────────────────────────────────────────
1307 (le_of_add_le_add_right (le_trans hl (inter_le_right _ _))))
id └────────────────────┘ └──────┘ └┘ └────────────┘
src ───┘ └────────────────────┘┴ └──────┘┴ ┴ └────────────┘└───────┘
typ ───┘ └────────────────────┘┴ └──────┘┴└┘┴ └────────────┘└───────┘
doc ───┘ ┴ ┴ ┴ └───────┘
txt ───┘ ┴ ┴ ┴ └───────┘
par ───┘ ┴ ┴ ┴ └───────┘
pid ───┘ ┴ ┴ ┴ └──────┘┴
st ────────────────────────────────────────────────────────────────┘
1308 end
st └─┘
1309
1310 theorem add_inter_distrib (s t u : multiset α) : s + (t ∩ u) = (s + t) ∩ (s + u) :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1311 by rw [add_comm, inter_add_distrib, add_comm s, add_comm s]
id └──────┘ └───────────────┘ └──────┘ ┴ └──────┘ ┴
src └──┘└──────┘└┘└───────────────┘└┘└──────┘┴ └┘└──────┘┴ └─
typ └──┘└──────┘└┘└───────────────┘└┘└──────┘┴┴└┘└──────┘┴┴└─
doc └──┘ └┘ └┘ ┴ └┘ ┴ └─
txt └──┘ └┘ └┘ ┴ └┘ ┴ └─
par └──┘ └┘ └┘ ┴ └┘ ┴ └─
pid └┘ └┘ └┘ ┴ └┘ ┴ ┴└
st └───────────┘└─────────────────┘└──────────┘└──────────┘┴└
1312
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1313 theorem cons_inter_distrib (a : α) (s t : multiset α) : a :: (s ∩ t) = (a :: s) ∩ (a :: t) :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴
src └──────┘ └┘ ┴ ┴ └┘ ┴ └┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘ └┘ └┘
1314 by simp
src └────
typ └────
doc └────
txt └────
par └────
pid └
st └─────
1315
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1316 theorem union_add_inter (s t : multiset α) : s ∪ t + s ∩ t = s + t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1317 begin
st └─────
1318 apply le_antisymm,
id └─────────┘
src └────┘└─────────┘
typ └────┘└─────────┘
doc └────┘
txt └────┘
par └────┘
pid ┴
st ──────────────────┘└─
1319 { rw union_add_distrib,
id └───────────────┘
src └─┘└───────────────┘
typ └─┘└───────────────┘
doc └─┘
txt └─┘
par └─┘
pid ┴
st ───┘└──────────────────┘└─
1320 refine union_le (add_le_add_left (inter_le_right _ _) _) _,
id └──────┘ └─────────────┘ └────────────┘
src └─────┘└──────┘┴ └─────────────┘┴ └────────────┘└────────┘
typ └─────┘└──────┘┴ └─────────────┘┴ └────────────┘└────────┘
doc └─────┘ ┴ ┴ └────────┘
txt └─────┘ ┴ ┴ └────────┘
par └─────┘ ┴ ┴ └────────┘
pid ┴ ┴ ┴ └────────┘
st ─────────────────────────────────────────────────────────────┘└─
1321 rw add_comm, exact add_le_add_right (inter_le_left _ _) _ },
id └──────┘ └──────────────┘ └───────────┘
src └─┘└──────┘ └────┘└──────────────┘┴ └───────────┘└──────┘
typ └─┘└──────┘ └────┘└──────────────┘┴ └───────────┘└──────┘
doc └─┘ └────┘ ┴ └──────┘
txt └─┘ └────┘ ┴ └──────┘
par └─┘ └────┘ ┴ └──────┘
pid ┴ ┴ ┴ └─────┘┴
st ──────────────┘└─────────────────────────────────────────────┘└┘└
1322 { rw [add_comm, add_inter_distrib],
id └──────┘ └───────────────┘
src └──┘└──────┘└┘└───────────────┘┴
typ └──┘└──────┘└┘└───────────────┘┴
doc └──┘ └┘ ┴
txt └──┘ └┘ ┴
par └──┘ └┘ ┴
pid └┘ └┘ ┴
st ───────────────┘└─────────────────┘└──
1323 refine le_inter (add_le_add_right (le_union_right _ _) _) _,
id └──────┘ └──────────────┘ └────────────┘
src └─────┘└──────┘┴ └──────────────┘┴ └────────────┘└────────┘
typ └─────┘└──────┘┴ └──────────────┘┴ └────────────┘└────────┘
doc └─────┘ ┴ ┴ └────────┘
txt └─────┘ ┴ ┴ └────────┘
par └─────┘ ┴ ┴ └────────┘
pid ┴ ┴ ┴ └────────┘
st ──────────────────────────────────────────────────────────────┘└─
1324 rw add_comm, exact add_le_add_right (le_union_left _ _) _ }
id └──────┘ └──────────────┘ └───────────┘
src └─┘└──────┘ └────┘└──────────────┘┴ └───────────┘└──────┘
typ └─┘└──────┘ └────┘└──────────────┘┴ └───────────┘└──────┘
doc └─┘ └────┘ ┴ └──────┘
txt └─┘ └────┘ ┴ └──────┘
par └─┘ └────┘ ┴ └──────┘
pid ┴ ┴ ┴ └─────┘┴
st ──────────────┘└─────────────────────────────────────────────┘└─
1325 end
st ──┘
1326
1327 theorem sub_add_inter (s t : multiset α) : s - t + s ∩ t = s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1328 begin
st └─────
1329 rw [inter_comm],
id └────────┘
src └──┘└────────┘┴
typ └──┘└────────┘┴
doc └──┘ ┴
txt └──┘ ┴
par └──┘ ┴
pid └┘ ┴
st ───────────────┘└──
1330 revert s, refine multiset.induction_on t (by simp) (λ a t IH s, _),
id └───────────────────┘ ┴
src └──────┘ └─────┘└───────────────────┘┴ ┴ ┴└──┘└┘ └───────────┘
typ └──────┘ └─────┘└───────────────────┘┴┴┴ ┴└──┘└┘ └───────────┘
doc └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
txt └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
par └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
pid └┘ ┴ ┴ ┴ └─────┘ └───────────┘
st ─────────┘└──────────────────────────────────┘└───┘└───────────────┘└─
1331 by_cases a ∈ s,
id ┴ ┴ ┴
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────┘└─
1332 { rw [cons_inter_of_pos _ h, sub_cons, add_cons, IH, cons_erase h] },
id └───────────────┘ ┴ └──────┘ └──────┘ └┘ └────────┘ ┴
src └──┘└───────────────┘└─┘ └┘└──────┘└┘└──────┘└┘ └┘└────────┘┴ └┘
typ └──┘└───────────────┘└─┘┴└┘└──────┘└┘└──────┘└┘└┘└┘└────────┘┴┴└┘
doc └──┘ └─┘ └┘ └┘ └┘ └┘ ┴ └┘
txt └──┘ └─┘ └┘ └┘ └┘ └┘ ┴ └┘
par └──┘ └─┘ └┘ └┘ └┘ └┘ ┴ └┘
pid └┘ └─┘ └┘ └┘ └┘ └┘ ┴ ┴┴
st ───┘└───────────────────────┘└────────┘└────────┘└──┘└────────────┘┴┴└┘└
1333 { rw [cons_inter_of_neg _ h, sub_cons, erase_of_not_mem h, IH] }
id └───────────────┘ ┴ └──────┘ └──────────────┘ ┴ └┘
src └──┘└───────────────┘└─┘ └┘└──────┘└┘└──────────────┘┴ └┘ └┘
typ └──┘└───────────────┘└─┘┴└┘└──────┘└┘└──────────────┘┴┴└┘└┘└┘
doc └──┘ └─┘ └┘ └┘ ┴ └┘ └┘
txt └──┘ └─┘ └┘ └┘ ┴ └┘ └┘
par └──┘ └─┘ └┘ └┘ ┴ └┘ └┘
pid └┘ └─┘ └┘ └┘ ┴ └┘ ┴┴
st ────────────────────────────┘└────────┘└──────────────────┘└──┘┴┴└─
1334 end
st ──┘
1335
1336 theorem sub_inter (s t : multiset α) : s - (s ∩ t) = s - t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
1337 add_right_cancel $
id └──────────────┘
src └──────────────┘
typ └──────────────┘
1338 by rw [sub_add_inter s t, sub_add_cancel (inter_le_left _ _)]
id └───────────┘ ┴ ┴ └────────────┘ └───────────┘
src └──┘└───────────┘┴ ┴ └┘└────────────┘┴ └───────────┘└──────
typ └──┘└───────────┘┴┴┴┴└┘└────────────┘┴ └───────────┘└──────
doc └──┘ ┴ ┴ └┘ ┴ └──────
txt └──┘ ┴ ┴ └┘ ┴ └──────
par └──┘ ┴ ┴ └┘ ┴ └──────
pid └┘ ┴ ┴ └┘ ┴ └────┘└
st └────────────────────┘└──────────────────────────────────┘┴└
1339
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1340 end
1341
1342
1343 /- filter -/
1344 section
1345 variables {p : α → Prop} [decidable_pred p]
id └────────────┘
src └────────────┘
typ └────────────┘
1346
1347 /-- `filter p s` returns the elements in `s` (with the same multiplicities)
1348 which satisfy `p`, and removes the rest. -/
1349 def filter (p : α → Prop) [h : decidable_pred p] (s : multiset α) : multiset α :=
id ┴ └────────────┘ ┴ └──────┘ ┴ └──────┘ ┴
src └────────────┘ └──────┘ └──────┘
typ ┴ └────────────┘ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
1350 quot.lift_on s (λ l, (filter p l : multiset α))
id └──────────┘ ┴ ┴ └────┘ ┴ ┴ └──────┘ ┴
src └──────────┘ └────┘ └──────┘
typ └──────────┘ ┴ ┴ └────┘ ┴ ┴ └──────┘ ┴
doc └──────┘
1351 (λ l₁ l₂ h, quot.sound $ perm_filter p h)
id └┘ └┘ ┴ └────────┘ └─────────┘ ┴ ┴
src └────────┘ └─────────┘
typ └┘ └┘ ┴ └────────┘ └─────────┘ ┴ ┴
1352
1353 @[simp] theorem coe_filter (p : α → Prop) [h : decidable_pred p]
id ┴ └────────────┘ ┴
src └────────────┘
typ ┴ └────────────┘ ┴
doc └──┘
1354 (l : list α) : filter p (↑l) = l.filter p := rfl
id └──┘ ┴ └────┘ ┴ ┴┴ ┴ ┴└─────┘ ┴ └─┘
src └──┘ └────┘ ┴ ┴ └─────┘ └─┘
typ └──┘ ┴ └────┘ ┴ ┴┴ ┴ ┴└─────┘ ┴ └─┘
doc └────┘
1355
1356 @[simp] theorem filter_zero (p : α → Prop) [h : decidable_pred p] : filter p 0 = 0 := rfl
id ┴ └────────────┘ ┴ └────┘ ┴ ┴ └─┘
src └────────────┘ └────┘ ┴ └─┘
typ ┴ └────────────┘ ┴ └────┘ ┴ ┴ └─┘
doc └──┘ └────┘
1357
1358 @[simp] theorem filter_cons_of_pos {a : α} (s) : p a → filter p (a::s) = a :: filter p s :=
id ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ ┴ └┘ └────┘ ┴ ┴
src └────┘ └┘ ┴ └┘ └────┘
typ ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ ┴ └┘ └────┘ ┴ ┴
doc └──┘ └────┘ └┘ └┘ └────┘
1359 quot.induction_on s $ λ l h, congr_arg coe $ filter_cons_of_pos l h
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └────────────────┘ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └────────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └────────────────┘ ┴ ┴
1360
1361 @[simp] theorem filter_cons_of_neg {a : α} (s) : ¬ p a → filter p (a::s) = filter p s :=
id ┴ ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ └────┘ ┴ ┴
src ┴ └────┘ └┘ ┴ └────┘
typ ┴ ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ └────┘ ┴ ┴
doc └──┘ └────┘ └┘ └────┘
1362 quot.induction_on s $ λ l h, @congr_arg _ _ _ _ coe $ filter_cons_of_neg l h
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └────────────────┘ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └────────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └────────────────┘ ┴ ┴
1363
1364 lemma filter_congr {p q : α → Prop} [decidable_pred p] [decidable_pred q]
id ┴ └────────────┘ ┴ └────────────┘ ┴
src └────────────┘ └────────────┘
typ ┴ └────────────┘ ┴ └────────────┘ ┴
1365 {s : multiset α} : (∀ x ∈ s, p x ↔ q x) → filter p s = filter q s :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └──────┘ ┴ └────┘ ┴ └────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └──────┘ └────┘ └────┘
1366 quot.induction_on s $ λ l h, congr_arg coe $ filter_congr h
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └──────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └──────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └──────────┘ ┴
1367
1368 @[simp] theorem filter_add (s t : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1369 filter p (s + t) = filter p s + filter p t :=
id └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └────┘ ┴ ┴ └────┘ ┴ └────┘
typ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────┘ └────┘
1370 quotient.induction_on₂ s t $ λ l₁ l₂, congr_arg coe $ filter_append _ _
id └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └───────────┘
src └────────────────────┘ └───────┘ └─┘ └───────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └───────────┘
1371
1372 @[simp] theorem filter_le (s : multiset α) : filter p s ≤ s :=
id └──────┘ ┴ └────┘ ┴ ┴ ┴ ┴
src └──────┘ └────┘ ┴
typ └──────┘ ┴ └────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └────┘
1373 quot.induction_on s $ λ l, subperm_of_sublist $ filter_sublist _
id └───────────────┘ ┴ ┴ └────────────────┘ └────────────┘
src └───────────────┘ └────────────────┘ └────────────┘
typ └───────────────┘ ┴ ┴ └────────────────┘ └────────────┘
1374
1375 @[simp] theorem filter_subset (s : multiset α) : filter p s ⊆ s :=
id └──────┘ ┴ └────┘ ┴ ┴ ┴ ┴
src └──────┘ └────┘ ┴
typ └──────┘ ┴ └────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └────┘
1376 subset_of_le $ filter_le _
id └──────────┘ └───────┘
src └──────────┘ └───────┘
typ └──────────┘ └───────┘
1377
1378 @[simp] theorem mem_filter {a : α} {s} : a ∈ filter p s ↔ a ∈ s ∧ p a :=
id ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └────┘ ┴ ┴ ┴
typ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └────┘
1379 quot.induction_on s $ λ l, mem_filter
id └───────────────┘ ┴ ┴ └────────┘
src └───────────────┘ └────────┘
typ └───────────────┘ ┴ ┴ └────────┘
1380
1381 theorem of_mem_filter {a : α} {s} (h : a ∈ filter p s) : p a :=
id ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴
src ┴ └────┘
typ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴
doc └────┘
1382 (mem_filter.1 h).2
id └────────┘┴ ┴ ┴
src └────────┘┴ ┴
typ └────────┘┴ ┴ ┴
1383
1384 theorem mem_of_mem_filter {a : α} {s} (h : a ∈ filter p s) : a ∈ s :=
id ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴
src ┴ └────┘ ┴
typ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴
doc └────┘
1385 (mem_filter.1 h).1
id └────────┘┴ ┴ ┴
src └────────┘┴ ┴
typ └────────┘┴ ┴ ┴
1386
1387 theorem mem_filter_of_mem {a : α} {l} (m : a ∈ l) (h : p a) : a ∈ filter p l :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
src ┴ ┴ └────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘
1388 mem_filter.2 ⟨m, h⟩
id └────────┘┴ ┴ ┴
src └────────┘┴
typ └────────┘┴ ┴ ┴
1389
1390 theorem filter_eq_self {s} : filter p s = s ↔ ∀ a ∈ s, p a :=
id └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └────┘ ┴ ┴
typ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └────┘
1391 quot.induction_on s $ λ l, iff.trans ⟨λ h,
id └───────────────┘ ┴ ┴ └───────┘ ┴
src └───────────────┘ └───────┘
typ └───────────────┘ ┴ ┴ └───────┘ ┴
1392 eq_of_sublist_of_length_eq (filter_sublist _) (@congr_arg _ _ _ _ card h),
id └────────────────────────┘ └────────────┘ └───────┘ └──┘ ┴
src └────────────────────────┘ └────────────┘ └───────┘ └──┘
typ └────────────────────────┘ └────────────┘ └───────┘ └──┘ ┴
doc └──┘
1393 congr_arg coe⟩ filter_eq_self
id └───────┘ └─┘ └────────────┘
src └───────┘ └─┘ └────────────┘
typ └───────┘ └─┘ └────────────┘
1394
1395 theorem filter_eq_nil {s} : filter p s = 0 ↔ ∀ a ∈ s, ¬p a :=
id └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴
src └────┘ ┴ ┴ ┴
typ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴
doc └────┘
1396 quot.induction_on s $ λ l, iff.trans ⟨λ h,
id └───────────────┘ ┴ ┴ └───────┘ ┴
src └───────────────┘ └───────┘
typ └───────────────┘ ┴ ┴ └───────┘ ┴
1397 eq_nil_of_length_eq_zero (@congr_arg _ _ _ _ card h),
id └──────────────────────┘ └───────┘ └──┘ ┴
src └──────────────────────┘ └───────┘ └──┘
typ └──────────────────────┘ └───────┘ └──┘ ┴
doc └──┘
1398 congr_arg coe⟩ filter_eq_nil
id └───────┘ └─┘ └───────────┘
src └───────┘ └─┘ └───────────┘
typ └───────┘ └─┘ └───────────┘
1399
1400 theorem filter_le_filter {s t} (h : s ≤ t) : filter p s ≤ filter p t :=
id ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src ┴ └────┘ ┴ └────┘
typ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────┘
1401 le_induction_on h $ λ l₁ l₂ h, subperm_of_sublist $ filter_sublist_filter h
id └─────────────┘ ┴ └┘ └┘ ┴ └────────────────┘ └───────────────────┘ ┴
src └─────────────┘ └────────────────┘ └───────────────────┘
typ └─────────────┘ ┴ └┘ └┘ ┴ └────────────────┘ └───────────────────┘ ┴
1402
1403 theorem le_filter {s t} : s ≤ filter p t ↔ s ≤ t ∧ ∀ a ∈ s, p a :=
id ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └────┘ ┴ ┴ ┴
typ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └────┘
1404 ⟨λ h, ⟨le_trans h (filter_le _), λ a m, of_mem_filter (mem_of_le h m)⟩,
id ┴ └──────┘ ┴ └───────┘ ┴ ┴ └───────────┘ └───────┘ ┴ ┴
src └──────┘ └───────┘ └───────────┘ └───────┘
typ ┴ └──────┘ ┴ └───────┘ ┴ ┴ └───────────┘ └───────┘ ┴ ┴
1405 λ ⟨h, al⟩, filter_eq_self.2 al ▸ filter_le_filter h⟩
id ┴┴ └┘ └────────────┘┴ ┴ └──────────────┘
src └────────────┘┴ ┴ └──────────────┘
typ ┴┴ └┘ └────────────┘┴ ┴ └──────────────┘
1406
1407 @[simp] theorem filter_sub [decidable_eq α] (s t : multiset α) :
id └──────────┘ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
1408 filter p (s - t) = filter p s - filter p t :=
id └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └────┘ ┴ ┴ └────┘ ┴ └────┘
typ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────┘ └────┘
1409 begin
st └─────
1410 revert s, refine multiset.induction_on t (by simp) (λ a t IH s, _),
id └───────────────────┘ ┴
src └──────┘ └─────┘└───────────────────┘┴ ┴ ┴└──┘└┘ └───────────┘
typ └──────┘ └─────┘└───────────────────┘┴┴┴ ┴└──┘└┘ └───────────┘
doc └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
txt └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
par └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
pid └┘ ┴ ┴ ┴ └─────┘ └───────────┘
st ─────────┘└──────────────────────────────────┘└───┘└───────────────┘└─
1411 rw [sub_cons, IH],
id └──────┘ └┘
src └──┘└──────┘└┘ ┴
typ └──┘└──────┘└┘└┘┴
doc └──┘ └┘ ┴
txt └──┘ └┘ ┴
par └──┘ └┘ ┴
pid └┘ └┘ ┴
st ─────────────┘└──┘└──
1412 by_cases p a,
id ┴ ┴
src └───────┘ ┴
typ └───────┘┴┴┴
doc └───────┘ ┴
txt └───────┘ ┴
par └───────┘ ┴
pid ┴ ┴
st ─────────────┘└─
1413 { rw [filter_cons_of_pos _ h, sub_cons], congr,
id └────────────────┘ ┴ └──────┘
src └──┘└────────────────┘└─┘ └┘└──────┘┴ └───┘
typ └──┘└────────────────┘└─┘┴└┘└──────┘┴ └───┘
doc └──┘ └─┘ └┘ ┴
txt └──┘ └─┘ └┘ ┴ └───┘
par └──┘ └─┘ └┘ ┴ └───┘
pid └┘ └─┘ └┘ ┴
st ───┘└────────────────────────┘└────────┘└──────┘└─
1414 by_cases m : a ∈ s,
id ┴ ┴ ┴
src └───────┘ └─┘ ┴┴┴
typ └───────┘ └─┘┴┴┴┴┴
doc └───────┘ └─┘ ┴ ┴
txt └───────┘ └─┘ ┴ ┴
par └───────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴
st ─────────────────────┘└─
1415 { rw [← cons_inj_right a, ← filter_cons_of_pos _ h,
id └────────────┘ ┴ └────────────────┘ ┴
src └────┘└────────────┘┴ └──┘└────────────────┘└─┘ └─
typ └────┘└────────────┘┴┴└──┘└────────────────┘└─┘┴└─
doc └────┘ ┴ └──┘ └─┘ └─
txt └────┘ ┴ └──┘ └─┘ └─
par └────┘ ┴ └──┘ └─┘ └─
pid └──┘ ┴ └──┘ └─┘ └─
st ─────┘└────────────────────┘└────────────────────────┘└─
1416 cons_erase (mem_filter_of_mem m h), cons_erase m] },
id └────────┘ └───────────────┘ ┴ ┴ └────────┘ ┴
src ─────────┘└────────┘┴ └───────────────┘┴ ┴ └─┘└────────┘┴ └┘
typ ─────────┘└────────┘┴ └───────────────┘┴┴┴┴└─┘└────────┘┴┴└┘
doc ─────────┘ ┴ ┴ ┴ └─┘ ┴ └┘
txt ─────────┘ ┴ ┴ ┴ └─┘ ┴ └┘
par ─────────┘ ┴ ┴ ┴ └─┘ ┴ └┘
pid ─────────┘ ┴ ┴ ┴ └─┘ ┴ ┴┴
st ───────────────────────────────────────────┘└────────────┘┴┴└┘└
1417 { rw [erase_of_not_mem m, erase_of_not_mem (mt mem_of_mem_filter m)] } },
id └──────────────┘ ┴ └──────────────┘ └┘ └───────────────┘ ┴
src └──┘└──────────────┘┴ └┘└──────────────┘┴ └┘┴└───────────────┘┴ └─┘
typ └──┘└──────────────┘┴┴└┘└──────────────┘┴ └┘┴└───────────────┘┴┴└─┘
doc └──┘ ┴ └┘ ┴ ┴ ┴ └─┘
txt └──┘ ┴ └┘ ┴ ┴ ┴ └─┘
par └──┘ ┴ └┘ ┴ ┴ ┴ └─┘
pid └┘ ┴ └┘ ┴ ┴ ┴ └┘┴
st ───────────────────────────┘└─────────────────────────────────────────┘┴┴└──┘└
1418 { rw [filter_cons_of_neg _ h],
id └────────────────┘ ┴
src └──┘└────────────────┘└─┘ ┴
typ └──┘└────────────────┘└─┘┴┴
doc └──┘ └─┘ ┴
txt └──┘ └─┘ ┴
par └──┘ └─┘ ┴
pid └┘ └─┘ ┴
st ─────────────────────────────┘└──
1419 by_cases m : a ∈ s,
id ┴ ┴
src └───────┘ └─┘ ┴ ┴
typ └───────┘ └─┘┴┴ ┴┴
doc └───────┘ └─┘ ┴ ┴
txt └───────┘ └─┘ ┴ ┴
par └───────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴
st ─────────────────────┘└─
1420 { rw [(by rw filter_cons_of_neg _ h : filter p (erase s a) = filter p (a :: erase s a)),
id └────────────────┘ ┴ ┴ └────┘ ┴ └┘ └───┘ ┴ ┴
src └──┘ └──┘└────────────────┘└─┘ └─┘ ┴ ┴ ┴ ┴ └┘┴┴└────┘┴ ┴ ┴└┘┴└───┘┴ ┴ └───
typ └──┘ └──┘└────────────────┘└─┘┴└─┘ ┴ ┴ ┴ ┴ └┘┴┴└────┘┴┴┴ ┴└┘┴└───┘┴┴┴┴└───
doc └──┘ └──┘ └─┘ └─┘ ┴ ┴ ┴ ┴ └┘ ┴└────┘┴ ┴ ┴└┘┴└───┘┴ ┴ └───
txt └──┘ └──┘ └─┘ └─┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───
par └──┘ └──┘ └─┘ └─┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───
pid └┘ └──┘ └─┘ └─┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───
st ─────┘└─────┘└─────────────────────────┘└─────────────────────────────────────────────────┘└─
1421 cons_erase m] },
id └────────┘ ┴
src ─────────┘└────────┘┴ └┘
typ ─────────┘└────────┘┴┴└┘
doc ─────────┘ ┴ └┘
txt ─────────┘ ┴ └┘
par ─────────┘ ┴ └┘
pid ─────────┘ ┴ ┴┴
st ─────────────────────┘┴┴└┘└
1422 { rw [erase_of_not_mem m] } }
id └──────────────┘ ┴
src └──┘└──────────────┘┴ └┘
typ └──┘└──────────────┘┴┴└┘
doc └──┘ ┴ └┘
txt └──┘ ┴ └┘
par └──┘ ┴ └┘
pid └┘ ┴ ┴┴
st ───────────────────────────┘┴┴└───
1423 end
st ──┘
1424
1425 @[simp] theorem filter_union [decidable_eq α] (s t : multiset α) :
id └──────────┘ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
1426 filter p (s ∪ t) = filter p s ∪ filter p t :=
id └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └────┘ ┴ ┴ └────┘ ┴ └────┘
typ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────┘ └────┘
1427 by simp [(∪), union]
id └───┘
src └────┘ └──┘└───┘└─
typ └────┘ └──┘└───┘└─
doc └────┘ └──┘└───┘└─
txt └────┘ └──┘ └─
par └────┘ └──┘ └─
pid ┴┴ └──┘ ┴└
st └──────────────────
1428
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1429 @[simp] theorem filter_inter [decidable_eq α] (s t : multiset α) :
id └──────────┘ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
1430 filter p (s ∩ t) = filter p s ∩ filter p t :=
id └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └────┘ ┴ ┴ └────┘ ┴ └────┘
typ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────┘ └────┘
1431 le_antisymm (le_inter
id └─────────┘ └──────┘
src └─────────┘ └──────┘
typ └─────────┘ └──────┘
1432 (filter_le_filter $ inter_le_left _ _)
id └──────────────┘ └───────────┘
src └──────────────┘ └───────────┘
typ └──────────────┘ └───────────┘
1433 (filter_le_filter $ inter_le_right _ _)) $ le_filter.2
id └──────────────┘ └────────────┘ └───────┘┴
src └──────────────┘ └────────────┘ └───────┘┴
typ └──────────────┘ └────────────┘ └───────┘┴
1434 ⟨inf_le_inf (filter_le _) (filter_le _),
id └────────┘ └───────┘ └───────┘
src └────────┘ └───────┘ └───────┘
typ └────────┘ └───────┘ └───────┘
1435 λ a h, of_mem_filter (mem_of_le (inter_le_left _ _) h)⟩
id ┴ ┴ └───────────┘ └───────┘ └───────────┘ ┴
src └───────────┘ └───────┘ └───────────┘
typ ┴ ┴ └───────────┘ └───────┘ └───────────┘ ┴
1436
1437 @[simp] theorem filter_filter {q} [decidable_pred q] (s : multiset α) :
id └────────────┘ ┴ └──────┘ ┴
src └────────────┘ └──────┘
typ └────────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
1438 filter p (filter q s) = filter (λ a, p a ∧ q a) s :=
id └────┘ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └────┘ └────┘ ┴ └────┘ ┴
typ └────┘ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └────┘ └────┘ └────┘
1439 quot.induction_on s $ λ l, congr_arg coe $ filter_filter l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └───────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────┘ ┴
1440
1441 theorem filter_add_filter {q} [decidable_pred q] (s : multiset α) :
id └────────────┘ ┴ └──────┘ ┴
src └────────────┘ └──────┘
typ └────────────┘ ┴ └──────┘ ┴
doc └──────┘
1442 filter p s + filter q s = filter (λ a, p a ∨ q a) s + filter (λ a, p a ∧ q a) s :=
id └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └────┘ ┴ └────┘ ┴ └────┘ ┴ ┴ └────┘ ┴
typ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └────┘ └────┘ └────┘ └────┘
1443 multiset.induction_on s rfl $ λ a s IH,
id └───────────────────┘ ┴ └─┘ ┴ ┴ └┘
src └───────────────────┘ └─┘
typ └───────────────────┘ ┴ └─┘ ┴ ┴ └┘
1444 by by_cases p a; by_cases q a; simp *
id ┴ ┴ ┴ ┴
src └───────┘ ┴ └───────┘ ┴ └──────
typ └───────┘┴┴┴ └───────┘┴┴┴ └──────
doc └───────┘ ┴ └───────┘ ┴ └──────
txt └───────┘ ┴ └───────┘ ┴ └──────
par └───────┘ ┴ └───────┘ ┴ └──────
pid ┴ ┴ ┴ ┴ ┴┴└
st └───────────────────────────────────
1445
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1446 theorem filter_add_not (s : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
1447 filter p s + filter (λ a, ¬ p a) s = s :=
id └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └────┘ ┴ └────┘ ┴ ┴
typ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └────┘ └────┘
1448 by rw [filter_add_filter, filter_eq_self.2, filter_eq_nil.2]; simp [decidable.em]
id └───────────────┘ └────────────┘ └───────────┘ └──────────┘
src └──┘└───────────────┘└┘└────────────┘└──┘└───────────┘└─┘ └────┘└──────────┘└─
typ └──┘└───────────────┘└┘└────────────┘└──┘└───────────┘└─┘ └────┘└──────────┘└─
doc └──┘ └┘ └──┘ └─┘ └────┘ └─
txt └──┘ └┘ └──┘ └─┘ └────┘ └─
par └──┘ └┘ └──┘ └─┘ └────┘ └─
pid └┘ └┘ └──┘ └─┘ ┴┴ ┴└
st └────────────────────┘└──────────────┘└───────────────┘└─┘└─────────────────────
1449
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
1450 /- filter_map -/
src ─────────────────
typ ─────────────────
doc ─────────────────
txt ─────────────────
par ─────────────────
pid ─────────────────
st ─────────────────
1451
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1452 /-- `filter_map f s` is a combination filter/map operation on `s`.
1453 The function `f : α → option β` is applied to each element of `s`;
1454 if `f a` is `some b` then `b` is added to the result, otherwise
1455 `a` is removed from the resulting multiset. -/
1456 def filter_map (f : α → option β) (s : multiset α) : multiset β :=
id ┴ └────┘ ┴ └──────┘ ┴ └──────┘ ┴
src └────┘ └──────┘ └──────┘
typ ┴ └────┘ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
1457 quot.lift_on s (λ l, (filter_map f l : multiset β))
id └──────────┘ ┴ ┴ └────────┘ ┴ ┴ └──────┘ ┴
src └──────────┘ └────────┘ └──────┘
typ └──────────┘ ┴ ┴ └────────┘ ┴ ┴ └──────┘ ┴
doc └──────┘
1458 (λ l₁ l₂ h, quot.sound $perm_filter_map f h)
id └┘ └┘ ┴ └────────┘ └─────────────┘ ┴ ┴
src └────────┘ └─────────────┘
typ └┘ └┘ ┴ └────────┘ └─────────────┘ ┴ ┴
1459
1460 @[simp] theorem coe_filter_map (f : α → option β) (l : list α) : filter_map f l = l.filter_map f := rfl
id ┴ └────┘ ┴ └──┘ ┴ └────────┘ ┴ ┴ ┴ ┴└─────────┘ ┴ └─┘
src └────┘ └──┘ └────────┘ ┴ └─────────┘ └─┘
typ ┴ └────┘ ┴ └──┘ ┴ └────────┘ ┴ ┴ ┴ ┴└─────────┘ ┴ └─┘
doc └──┘ └────────┘
1461
1462 @[simp] theorem filter_map_zero (f : α → option β) : filter_map f 0 = 0 := rfl
id ┴ └────┘ ┴ └────────┘ ┴ ┴ └─┘
src └────┘ └────────┘ ┴ └─┘
typ ┴ └────┘ ┴ └────────┘ ┴ ┴ └─┘
doc └──┘ └────────┘
1463
1464 @[simp] theorem filter_map_cons_none {f : α → option β} (a : α) (s : multiset α) (h : f a = none) :
id ┴ └────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └──┘
src └────┘ └──────┘ ┴ └──┘
typ ┴ └────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └──┘
doc └──┘ └──────┘
1465 filter_map f (a :: s) = filter_map f s :=
id └────────┘ ┴ ┴ └┘ ┴ ┴ └────────┘ ┴ ┴
src └────────┘ └┘ ┴ └────────┘
typ └────────┘ ┴ ┴ └┘ ┴ ┴ └────────┘ ┴ ┴
doc └────────┘ └┘ └────────┘
1466 quot.induction_on s $ λ l, @congr_arg _ _ _ _ coe $ filter_map_cons_none a l h
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └──────────────────┘ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └──────────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └──────────────────┘ ┴ ┴ ┴
1467
1468 @[simp] theorem filter_map_cons_some (f : α → option β)
id ┴ └────┘ ┴
src └────┘
typ ┴ └────┘ ┴
doc └──┘
1469 (a : α) (s : multiset α) {b : β} (h : f a = some b) :
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴
src └──────┘ ┴ └──┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴
doc └──────┘
1470 filter_map f (a :: s) = b :: filter_map f s :=
id └────────┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ └────────┘ ┴ ┴
src └────────┘ └┘ ┴ └┘ └────────┘
typ └────────┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ └────────┘ ┴ ┴
doc └────────┘ └┘ └┘ └────────┘
1471 quot.induction_on s $ λ l, @congr_arg _ _ _ _ coe $ filter_map_cons_some f a l h
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └──────────────────┘ ┴ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └──────────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └──────────────────┘ ┴ ┴ ┴ ┴
1472
1473 theorem filter_map_eq_map (f : α → β) : filter_map (some ∘ f) = map f :=
id ┴ ┴ └────────┘ └──┘ ┴ ┴ ┴ └─┘ ┴
src └────────┘ └──┘ ┴ ┴ └─┘
typ ┴ ┴ └────────┘ └──┘ ┴ ┴ ┴ └─┘ ┴
doc └────────┘ └─┘
1474 funext $ λ s, quot.induction_on s $ λ l,
id └────┘ ┴ └───────────────┘ ┴ ┴
src └────┘ └───────────────┘
typ └────┘ ┴ └───────────────┘ ┴ ┴
1475 @congr_arg _ _ _ _ coe $ congr_fun (filter_map_eq_map f) l
id └───────┘ └─┘ └───────┘ └───────────────┘ ┴ ┴
src └───────┘ └─┘ └───────┘ └───────────────┘
typ └───────┘ └─┘ └───────┘ └───────────────┘ ┴ ┴
1476
1477 theorem filter_map_eq_filter (p : α → Prop) [decidable_pred p] :
id ┴ └────────────┘ ┴
src └────────────┘
typ ┴ └────────────┘ ┴
1478 filter_map (option.guard p) = filter p :=
id └────────┘ └──────────┘ ┴ ┴ └────┘ ┴
src └────────┘ └──────────┘ ┴ └────┘
typ └────────┘ └──────────┘ ┴ ┴ └────┘ ┴
doc └────────┘ └──────────┘ └────┘
1479 funext $ λ s, quot.induction_on s $ λ l,
id └────┘ ┴ └───────────────┘ ┴ ┴
src └────┘ └───────────────┘
typ └────┘ ┴ └───────────────┘ ┴ ┴
1480 @congr_arg _ _ _ _ coe $ congr_fun (filter_map_eq_filter p) l
id └───────┘ └─┘ └───────┘ └──────────────────┘ ┴ ┴
src └───────┘ └─┘ └───────┘ └──────────────────┘
typ └───────┘ └─┘ └───────┘ └──────────────────┘ ┴ ┴
1481
1482 theorem filter_map_filter_map (f : α → option β) (g : β → option γ) (s : multiset α) :
id ┴ └────┘ ┴ ┴ └────┘ ┴ └──────┘ ┴
src └────┘ └────┘ └──────┘
typ ┴ └────┘ ┴ ┴ └────┘ ┴ └──────┘ ┴
doc └──────┘
1483 filter_map g (filter_map f s) = filter_map (λ x, (f x).bind g) s :=
id └────────┘ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └──┘ ┴ ┴
src └────────┘ └────────┘ ┴ └────────┘ └──┘
typ └────────┘ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └──┘ ┴ ┴
doc └────────┘ └────────┘ └────────┘
1484 quot.induction_on s $ λ l, congr_arg coe $ filter_map_filter_map f g l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴ ┴ ┴
1485
1486 theorem map_filter_map (f : α → option β) (g : β → γ) (s : multiset α) :
id ┴ └────┘ ┴ ┴ ┴ └──────┘ ┴
src └────┘ └──────┘
typ ┴ └────┘ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
1487 map g (filter_map f s) = filter_map (λ x, (f x).map g) s :=
id └─┘ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └─┘ ┴ ┴
src └─┘ └────────┘ ┴ └────────┘ └─┘
typ └─┘ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └─┘ ┴ ┴
doc └─┘ └────────┘ └────────┘
1488 quot.induction_on s $ λ l, congr_arg coe $ map_filter_map f g l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └────────────┘ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └────────────┘ ┴ ┴ ┴
1489
1490 theorem filter_map_map (f : α → β) (g : β → option γ) (s : multiset α) :
id ┴ ┴ ┴ └────┘ ┴ └──────┘ ┴
src └────┘ └──────┘
typ ┴ ┴ ┴ └────┘ ┴ └──────┘ ┴
doc └──────┘
1491 filter_map g (map f s) = filter_map (g ∘ f) s :=
id └────────┘ ┴ └─┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ ┴
src └────────┘ └─┘ ┴ └────────┘ ┴
typ └────────┘ ┴ └─┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ ┴
doc └────────┘ └─┘ └────────┘
1492 quot.induction_on s $ λ l, congr_arg coe $ filter_map_map f g l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └────────────┘ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └────────────┘ ┴ ┴ ┴
1493
1494 theorem filter_filter_map (f : α → option β) (p : β → Prop) [decidable_pred p] (s : multiset α) :
id ┴ └────┘ ┴ ┴ └────────────┘ ┴ └──────┘ ┴
src └────┘ └────────────┘ └──────┘
typ ┴ └────┘ ┴ ┴ └────────────┘ ┴ └──────┘ ┴
doc └──────┘
1495 filter p (filter_map f s) = filter_map (λ x, (f x).filter p) s :=
id └────┘ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └────┘ └────────┘ ┴ └────────┘ └────┘
typ └────┘ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────────┘ └────────┘ └────┘
1496 quot.induction_on s $ λ l, congr_arg coe $ filter_filter_map f p l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────┘ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────┘ ┴ ┴ ┴
1497
1498 theorem filter_map_filter (p : α → Prop) [decidable_pred p] (f : α → option β) (s : multiset α) :
id ┴ └────────────┘ ┴ ┴ └────┘ ┴ └──────┘ ┴
src └────────────┘ └────┘ └──────┘
typ ┴ └────────────┘ ┴ ┴ └────┘ ┴ └──────┘ ┴
doc └──────┘
1499 filter_map f (filter p s) = filter_map (λ x, if p x then f x else none) s :=
id └────────┘ ┴ └────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴
src └────────┘ └────┘ ┴ └────────┘ └──┘
typ └────────┘ ┴ └────┘ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴
doc └────────┘ └────┘ └────────┘
1500 quot.induction_on s $ λ l, congr_arg coe $ filter_map_filter p f l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────┘ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────┘ ┴ ┴ ┴
1501
1502 @[simp] theorem filter_map_some (s : multiset α) : filter_map some s = s :=
id └──────┘ ┴ └────────┘ └──┘ ┴ ┴ ┴
src └──────┘ └────────┘ └──┘ ┴
typ └──────┘ ┴ └────────┘ └──┘ ┴ ┴ ┴
doc └──┘ └──────┘ └────────┘
1503 quot.induction_on s $ λ l, congr_arg coe $ filter_map_some l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └─────────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └─────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └─────────────┘ ┴
1504
1505 @[simp] theorem mem_filter_map (f : α → option β) (s : multiset α) {b : β} :
id ┴ └────┘ ┴ └──────┘ ┴ ┴
src └────┘ └──────┘
typ ┴ └────┘ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘
1506 b ∈ filter_map f s ↔ ∃ a, a ∈ s ∧ f a = some b :=
id ┴ ┴ └────────┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴
src ┴ └────────┘ ┴ ┴ ┴ ┴ ┴ ┴ └──┘
typ ┴ ┴ └────────┘ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴
doc └────────┘
1507 quot.induction_on s $ λ l, mem_filter_map f l
id └───────────────┘ ┴ ┴ └────────────┘ ┴ ┴
src └───────────────┘ └────────────┘
typ └───────────────┘ ┴ ┴ └────────────┘ ┴ ┴
1508
1509 theorem map_filter_map_of_inv (f : α → option β) (g : β → α)
id ┴ └────┘ ┴ ┴ ┴
src └────┘
typ ┴ └────┘ ┴ ┴ ┴
1510 (H : ∀ x : α, (f x).map g = some x) (s : multiset α) :
id ┴ ┴ ┴ └─┘ ┴ ┴ └──┘ ┴ └──────┘ ┴
src └─┘ ┴ └──┘ └──────┘
typ ┴ ┴ ┴ └─┘ ┴ ┴ └──┘ ┴ └──────┘ ┴
doc └──────┘
1511 map g (filter_map f s) = s :=
id └─┘ ┴ └────────┘ ┴ ┴ ┴ ┴
src └─┘ └────────┘ ┴
typ └─┘ ┴ └────────┘ ┴ ┴ ┴ ┴
doc └─┘ └────────┘
1512 quot.induction_on s $ λ l, congr_arg coe $ map_filter_map_of_inv f g H l
id └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴ ┴ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────────┘
typ └───────────────┘ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴ ┴ ┴ ┴
1513
1514 theorem filter_map_le_filter_map (f : α → option β) {s t : multiset α}
id ┴ └────┘ ┴ └──────┘ ┴
src └────┘ └──────┘
typ ┴ └────┘ ┴ └──────┘ ┴
doc └──────┘
1515 (h : s ≤ t) : filter_map f s ≤ filter_map f t :=
id ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴
src ┴ └────────┘ ┴ └────────┘
typ ┴ ┴ ┴ └────────┘ ┴ ┴ ┴ └────────┘ ┴ ┴
doc └────────┘ └────────┘
1516 le_induction_on h $ λ l₁ l₂ h,
id └─────────────┘ ┴ └┘ └┘ ┴
src └─────────────┘
typ └─────────────┘ ┴ └┘ └┘ ┴
1517 subperm_of_sublist $ filter_map_sublist_filter_map _ h
id └────────────────┘ └───────────────────────────┘ ┴
src └────────────────┘ └───────────────────────────┘
typ └────────────────┘ └───────────────────────────┘ ┴
1518
1519 /- powerset -/
1520
1521 def powerset_aux (l : list α) : list (multiset α) :=
id └──┘ ┴ └──┘ └──────┘ ┴
src └──┘ └──┘ └──────┘
typ └──┘ ┴ └──┘ └──────┘ ┴
doc └──────┘
1522 0 :: sublists_aux l (λ x y, x :: y)
id └┘ └──────────┘ ┴ ┴ ┴ ┴ └┘ ┴
src └┘ └──────────┘ └┘
typ └┘ └──────────┘ ┴ ┴ ┴ ┴ └┘ ┴
1523
1524 theorem powerset_aux_eq_map_coe {l : list α} :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1525 powerset_aux l = (sublists l).map coe :=
id └──────────┘ ┴ ┴ └──────┘ ┴ └─┘ └─┘
src └──────────┘ ┴ └──────┘ └─┘ └─┘
typ └──────────┘ ┴ ┴ └──────┘ ┴ └─┘ └─┘
doc └──────┘
1526 by simp [powerset_aux, sublists];
id └──────────┘ └──────┘
src └────┘└──────────┘└┘└──────┘┴
typ └────┘└──────────┘└┘└──────┘┴
doc └────┘ └┘└──────┘┴
txt └────┘ └┘ ┴
par └────┘ └┘ ┴
pid ┴┴ └┘ ┴
st └───────────────────────────────
1527 rw [← show @sublists_aux₁ α (multiset α) l (λ x, [↑x]) =
id └───────────┘ └──────┘ ┴ ┴┴ ┴ ┴
src └────┘ ┴ └───────────┘┴ ┴ └──────┘┴ └┘ ┴ └──┘┴┴ ┴└┘┴└
typ └────┘ ┴ └───────────┘┴ ┴ └──────┘┴┴└┘ ┴ └──┘┴┴ ┴└┘┴└
doc └────┘ ┴ ┴ ┴ └──────┘┴ └┘ ┴ └──┘ └┘ └
txt └────┘ ┴ ┴ ┴ ┴ └┘ ┴ └──┘ └┘ └
par └────┘ ┴ ┴ ┴ ┴ └┘ ┴ └──┘ └┘ └
pid └──┘ ┴ ┴ ┴ ┴ └┘ ┴ └──┘ └┘ └
st ──────┘└────────────────────────────────────────────────────
1528 sublists_aux l (λ x, list.cons ↑x),
id └──────────┘ ┴ └───────┘
src ─────────────┘└──────────┘┴ ┴ └──┘└───────┘┴ └──
typ ─────────────┘└──────────┘┴┴┴ └──┘└───────┘┴ └──
doc ─────────────┘ ┴ ┴ └──┘ ┴ └──
txt ─────────────┘ ┴ ┴ └──┘ ┴ └──
par ─────────────┘ ┴ ┴ └──┘ ┴ └──
pid ─────────────┘ ┴ ┴ └──┘ ┴ └──
st ──────────────────────────────────────────────────
1529 from sublists_aux₁_eq_sublists_aux _ _,
id └───────────────────────────┘
src ─────────────┘└───────────────────────────┘└─────
typ ─────────────┘└───────────────────────────┘└─────
doc ─────────────┘ └─────
txt ─────────────┘ └─────
par ─────────────┘ └─────
pid ─────────────┘ └─────
st ──────────────────────────────────────────────┘└─
1530 sublists_aux_cons_eq_sublists_aux₁,
id └────────────────────────────────┘
src ──────┘└────────────────────────────────┘└─
typ ──────┘└────────────────────────────────┘└─
doc ──────┘ └─
txt ──────┘ └─
par ──────┘ └─
pid ──────┘ └─
st ────────────────────────────────────────┘└─
1531 ← bind_ret_eq_map, sublists_aux₁_bind]; refl
id └─────────────┘ └────────────────┘
src ────────┘└─────────────┘└┘└────────────────┘┴ └────
typ ────────┘└─────────────┘└┘└────────────────┘┴ └────
doc ────────┘ └┘ ┴ └────
txt ────────┘ └┘ ┴ └────
par ────────┘ └┘ ┴ └────
pid ────────┘ └┘ ┴ └
st ───────────────────────┘└──────────────────┘┴└──────
1532
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1533 @[simp] theorem mem_powerset_aux {l : list α} {s} :
id └──┘ ┴
src └──┘
typ └──┘ ┴
doc └──┘
1534 s ∈ powerset_aux l ↔ s ≤ ↑l :=
id ┴ ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴┴
src ┴ └──────────┘ ┴ ┴ ┴
typ ┴ ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴┴
1535 quotient.induction_on s $
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
1536 by simp [powerset_aux_eq_map_coe, subperm, and.comm]
id └─────────────────────┘ └─────┘ └──────┘
src └────┘└─────────────────────┘└┘└─────┘└┘└──────┘└─
typ └────┘└─────────────────────┘└┘└─────┘└┘└──────┘└─
doc └────┘ └┘└─────┘└┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └──────────────────────────────────────────────────
1537
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1538 def powerset_aux' (l : list α) : list (multiset α) := (sublists' l).map coe
id └──┘ ┴ └──┘ └──────┘ ┴ └───────┘ ┴ └─┘ └─┘
src └──┘ └──┘ └──────┘ └───────┘ └─┘ └─┘
typ └──┘ ┴ └──┘ └──────┘ ┴ └───────┘ ┴ └─┘ └─┘
doc └──────┘ └───────┘
1539
1540 theorem powerset_aux_perm_powerset_aux' {l : list α} :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1541 powerset_aux l ~ powerset_aux' l :=
id └──────────┘ ┴ ┴ └───────────┘ ┴
src └──────────┘ ┴ └───────────┘
typ └──────────┘ ┴ ┴ └───────────┘ ┴
doc ┴
1542 by rw powerset_aux_eq_map_coe; exact
id └─────────────────────┘
src └─┘└─────────────────────┘ └────┘
typ └─┘└─────────────────────┘ └────┘
doc └─┘ └────┘
txt └─┘ └────┘
par └─┘ └────┘
pid ┴ ┴
st └──────────────────────────────────
1543 perm_map _ (sublists_perm_sublists' _)
id └──────┘ └─────────────────────┘
src └──────┘└─┘ └─────────────────────┘└───
typ └──────┘└─┘ └─────────────────────┘└───
doc └─┘ └───
txt └─┘ └───
par └─┘ └───
pid └─┘ └─┘└
st ───────────────────────────────────────
1544
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1545 @[simp] theorem powerset_aux'_nil : powerset_aux' (@nil α) = [0] := rfl
id └───────────┘ └─┘ ┴ ┴ ┴ ┴ └─┘
src └───────────┘ └─┘ ┴ ┴ ┴ └─┘
typ └───────────┘ └─┘ ┴ ┴ ┴ ┴ └─┘
doc └──┘
1546
1547 @[simp] theorem powerset_aux'_cons (a : α) (l : list α) :
id ┴ └──┘ ┴
src └──┘
typ ┴ └──┘ ┴
doc └──┘
1548 powerset_aux' (a::l) = powerset_aux' l ++ list.map (cons a) (powerset_aux' l) :=
id └───────────┘ ┴└┘┴ ┴ └───────────┘ ┴ └┘ └──────┘ └──┘ ┴ └───────────┘ ┴
src └───────────┘ └┘ ┴ └───────────┘ └┘ └──────┘ └──┘ └───────────┘
typ └───────────┘ ┴└┘┴ ┴ └───────────┘ ┴ └┘ └──────┘ └──┘ ┴ └───────────┘ ┴
doc └──┘
1549 by simp [powerset_aux']; refl
id └───────────┘
src └────┘└───────────┘┴ └────
typ └────┘└───────────┘┴ └────
doc └────┘ ┴ └────
txt └────┘ ┴ └────
par └────┘ ┴ └────
pid ┴┴ ┴ └
st └───────────────────────────
1550
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1551 theorem powerset_aux'_perm {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id └──┘ ┴ └┘ ┴ └┘
src └──┘ ┴
typ └──┘ ┴ └┘ ┴ └┘
doc ┴
1552 powerset_aux' l₁ ~ powerset_aux' l₂ :=
id └───────────┘ └┘ ┴ └───────────┘ └┘
src └───────────┘ ┴ └───────────┘
typ └───────────┘ └┘ ┴ └───────────┘ └┘
doc ┴
1553 begin
st └─────
1554 induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {simp},
id ┴
src └────────┘ └─────────────────────────────────────────────┘ └──┘
typ └────────┘┴└─────────────────────────────────────────────┘ └──┘
doc └────────┘ └─────────────────────────────────────────────┘ └──┘
txt └────────┘ └─────────────────────────────────────────────┘ └──┘
par └────────┘ └─────────────────────────────────────────────┘ └──┘
pid ┴ ┴└────────────────────────────────────────────┘
st ───────────────────────────────────────────────────────────┘└─────┘└┘└
1555 { simp, exact perm_app IH (perm_map _ IH) },
id └──────┘ └──────┘ └┘
src └──┘ └────┘└──────┘┴ ┴ └──────┘└─┘ └┘
typ └──┘ └────┘└──────┘┴ ┴ └──────┘└─┘└┘└┘
doc └──┘ └────┘ ┴ ┴ └─┘ └┘
txt └──┘ └────┘ ┴ ┴ └─┘ └┘
par └──┘ └────┘ ┴ ┴ └─┘ └┘
pid ┴ ┴ ┴ └─┘ ┴┴
st ───┘└──┘└──────────────────────────────────┘└┘└
1556 { simp, apply perm_app_right,
id └────────────┘
src └──┘ └────┘└────────────┘
typ └──┘ └────┘└────────────┘
doc └──┘ └────┘
txt └──┘ └────┘
par └──┘ └────┘
pid ┴
st ───┘└──┘└────────────────────┘└─
1557 rw [← append_assoc, ← append_assoc,
id └──────────┘ └──────────┘
src └────┘└──────────┘└──┘└──────────┘└─
typ └────┘└──────────┘└──┘└──────────┘└─
doc └────┘ └──┘ └─
txt └────┘ └──┘ └─
par └────┘ └──┘ └─
pid └──┘ └──┘ └─
st ─────────────────────┘└──────────────┘└─
1558 (by funext s; simp [cons_swap] : cons b ∘ cons a = cons a ∘ cons b)],
id └───────┘ ┴ ┴ ┴ └──┘ ┴
src ───────┘ ┴└──────┘└┘└────┘└───────┘└┘└┘ ┴ ┴┴┴ ┴ ┴┴┴ ┴ ┴ ┴└──┘┴ └┘
typ ───────┘ ┴└──────┘└┘└────┘└───────┘└┘└┘ ┴ ┴┴┴ ┴ ┴┴┴ ┴┴┴ ┴└──┘┴┴└┘
doc ───────┘ ┴└──────┘└┘└────┘ └┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└──┘┴ └┘
txt ───────┘ ┴└──────┘└┘└────┘ └┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
par ───────┘ ┴└──────┘└┘└────┘ └┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
pid ───────┘ └───────────────┘ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
st ──────────┘└──────────────────────────┘└──────────────────────────────────┘└──
1559 exact perm_app_left _ perm_app_comm },
id └───────────┘ └───────────┘
src └────┘└───────────┘└─┘└───────────┘┴
typ └────┘└───────────┘└─┘└───────────┘┴
doc └────┘ └─┘ ┴
txt └────┘ └─┘ ┴
par └────┘ └─┘ ┴
pid ┴ └─┘ ┴
st ───────────────────────────────────────┘└┘└
1560 { exact IH₁.trans IH₂ }
id └───────┘ └─┘
src └────┘└───────┘┴ ┴
typ └────┘└───────┘┴└─┘┴
doc └────┘ ┴ ┴
txt └────┘ ┴ ┴
par └────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────────────┘└─
1561 end
st ──┘
1562
1563 theorem powerset_aux_perm {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id └──┘ ┴ └┘ ┴ └┘
src └──┘ ┴
typ └──┘ ┴ └┘ ┴ └┘
doc ┴
1564 powerset_aux l₁ ~ powerset_aux l₂ :=
id └──────────┘ └┘ ┴ └──────────┘ └┘
src └──────────┘ ┴ └──────────┘
typ └──────────┘ └┘ ┴ └──────────┘ └┘
doc ┴
1565 powerset_aux_perm_powerset_aux'.trans $
id └─────────────────────────────┘└────┘
src └─────────────────────────────┘└────┘
typ └─────────────────────────────┘└────┘
1566 (powerset_aux'_perm p).trans powerset_aux_perm_powerset_aux'.symm
id └────────────────┘ ┴ └───┘ └─────────────────────────────┘└───┘
src └────────────────┘ └───┘ └─────────────────────────────┘└───┘
typ └────────────────┘ ┴ └───┘ └─────────────────────────────┘└───┘
1567
1568 def powerset (s : multiset α) : multiset (multiset α) :=
id └──────┘ ┴ └──────┘ └──────┘ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘
1569 quot.lift_on s
id └──────────┘ ┴
src └──────────┘
typ └──────────┘ ┴
1570 (λ l, (powerset_aux l : multiset (multiset α)))
id ┴ └──────────┘ ┴ └──────┘ └──────┘ ┴
src └──────────┘ └──────┘ └──────┘
typ ┴ └──────────┘ ┴ └──────┘ └──────┘ ┴
doc └──────┘ └──────┘
1571 (λ l₁ l₂ h, quot.sound (powerset_aux_perm h))
id └┘ └┘ ┴ └────────┘ └───────────────┘ ┴
src └────────┘ └───────────────┘
typ └┘ └┘ ┴ └────────┘ └───────────────┘ ┴
1572
1573 theorem powerset_coe (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1574 @powerset α l = ((sublists l).map coe : list (multiset α)) :=
id └──────┘ ┴ ┴ ┴ └──────┘ ┴ └─┘ └─┘ └──┘ └──────┘ ┴
src └──────┘ ┴ └──────┘ └─┘ └─┘ └──┘ └──────┘
typ └──────┘ ┴ ┴ ┴ └──────┘ ┴ └─┘ └─┘ └──┘ └──────┘ ┴
doc └──────┘ └──────┘
1575 congr_arg coe powerset_aux_eq_map_coe
id └───────┘ └─┘ └─────────────────────┘
src └───────┘ └─┘ └─────────────────────┘
typ └───────┘ └─┘ └─────────────────────┘
1576
1577 @[simp] theorem powerset_coe' (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
doc └──┘
1578 @powerset α l = ((sublists' l).map coe : list (multiset α)) :=
id └──────┘ ┴ ┴ ┴ └───────┘ ┴ └─┘ └─┘ └──┘ └──────┘ ┴
src └──────┘ ┴ └───────┘ └─┘ └─┘ └──┘ └──────┘
typ └──────┘ ┴ ┴ ┴ └───────┘ ┴ └─┘ └─┘ └──┘ └──────┘ ┴
doc └───────┘ └──────┘
1579 quot.sound powerset_aux_perm_powerset_aux'
id └────────┘ └─────────────────────────────┘
src └────────┘ └─────────────────────────────┘
typ └────────┘ └─────────────────────────────┘
1580
1581 @[simp] theorem powerset_zero : @powerset α 0 = 0::0 := rfl
id └──────┘ ┴ ┴ └┘ └─┘
src └──────┘ ┴ └┘ └─┘
typ └──────┘ ┴ ┴ └┘ └─┘
doc └──┘ └┘
1582
1583 @[simp] theorem powerset_cons (a : α) (s) :
id ┴
typ ┴
doc └──┘
1584 powerset (a::s) = powerset s + map (cons a) (powerset s) :=
id └──────┘ ┴└┘┴ ┴ └──────┘ ┴ ┴ └─┘ └──┘ ┴ └──────┘ ┴
src └──────┘ └┘ ┴ └──────┘ ┴ └─┘ └──┘ └──────┘
typ └──────┘ ┴└┘┴ ┴ └──────┘ ┴ ┴ └─┘ └──┘ ┴ └──────┘ ┴
doc └┘ └─┘ └──┘
1585 quotient.induction_on s $ λ l, by simp; refl
id └───────────────────┘ ┴ ┴
src └───────────────────┘ └──┘ └────
typ └───────────────────┘ ┴ ┴ └──┘ └────
doc └──┘ └────
txt └──┘ └────
par └──┘ └────
pid └
st └───────────
1586
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1587 @[simp] theorem mem_powerset {s t : multiset α} :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1588 s ∈ powerset t ↔ s ≤ t :=
id ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴
src ┴ └──────┘ ┴ ┴
typ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴
1589 quotient.induction_on₂ s t $ by simp [subperm, and.comm]
id └────────────────────┘ ┴ ┴ └─────┘ └──────┘
src └────────────────────┘ └────┘└─────┘└┘└──────┘└─
typ └────────────────────┘ ┴ ┴ └────┘└─────┘└┘└──────┘└─
doc └────┘└─────┘└┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └─────────────────────────
1590
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1591 theorem map_single_le_powerset (s : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
1592 s.map (λ a, a::0) ≤ powerset s :=
id ┴└──┘ ┴ ┴└┘ ┴ └──────┘ ┴
src └──┘ └┘ ┴ └──────┘
typ ┴└──┘ ┴ ┴└┘ ┴ └──────┘ ┴
doc └──┘ └┘
1593 quotient.induction_on s $ λ l, begin
id └───────────────────┘ ┴ ┴
src └───────────────────┘
typ └───────────────────┘ ┴ ┴
st └─────
1594 simp [powerset_coe],
id └──────────┘
src └────┘└──────────┘┴
typ └────┘└──────────┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st ────────────────────┘└─
1595 show l.map (coe ∘ list.ret) <+~ (sublists l).map coe,
id └───┘ ┴ └──────┘ └─┘ └──────┘ ┴ └─┘
src └───┘└───┘┴ ┴┴┴└──────┘└┘└─┘┴ └──────┘┴ └────┘└─┘
typ └───┘└───┘┴ ┴┴┴└──────┘└┘└─┘┴ └──────┘┴┴└────┘└─┘
doc └───┘ ┴ ┴ ┴ └┘└─┘┴ └──────┘┴ └────┘
txt └───┘ ┴ ┴ ┴ └┘ ┴ ┴ └────┘
par └───┘ ┴ ┴ ┴ └┘ ┴ ┴ └────┘
pid └───┘ ┴ ┴ ┴ └┘ ┴ ┴ └────┘
st ─────────────────────────────────────────────────────┘└─
1596 rw ← list.map_map,
id └──────────┘
src └───┘└──────────┘
typ └───┘└──────────┘
doc └───┘
txt └───┘
par └───┘
pid └─┘
st ──────────────────┘└─
1597 exact subperm_of_sublist
id └────────────────┘
src └────┘└────────────────┘└
typ └────┘└────────────────┘└
doc └────┘ └
txt └────┘ └
par └────┘ └
pid ┴ └
st ───────────────────────────
1598 (map_sublist_map _ (map_ret_sublist_sublists _))
id └─────────────┘ └──────────────────────┘
src ───┘ └─────────────┘└─┘ └──────────────────────┘└───┘
typ ───┘ └─────────────┘└─┘ └──────────────────────┘└───┘
doc ───┘ └─┘ └───┘
txt ───┘ └─┘ └───┘
par ───┘ └─┘ └───┘
pid ───┘ └─┘ └──┘┴
st ────────────────────────────────────────────────────┘
1599 end
st └─┘
1600
1601 @[simp] theorem card_powerset (s : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1602 card (powerset s) = 2 ^ card s :=
id └──┘ └──────┘ ┴ ┴ ┴ └──┘ ┴
src └──┘ └──────┘ ┴ ┴ └──┘
typ └──┘ └──────┘ ┴ ┴ ┴ └──┘ ┴
doc └──┘ └──┘
1603 quotient.induction_on s $ by simp
id └───────────────────┘ ┴
src └───────────────────┘ └────
typ └───────────────────┘ ┴ └────
doc └────
txt └────
par └────
pid └
st └─────
1604
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
1605 /- antidiagonal -/
src ───────────────────
typ ───────────────────
doc ───────────────────
txt ───────────────────
par ───────────────────
pid ───────────────────
st ───────────────────
1606
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1607 theorem revzip_powerset_aux {l : list α} ⦃x⦄
id └──┘ ┴
src └──┘
typ └──┘ ┴
1608 (h : x ∈ revzip (powerset_aux l)) : x.1 + x.2 = ↑l :=
id ┴ ┴ └────┘ └──────────┘ ┴ ┴┴ ┴ ┴┴ ┴ ┴┴
src ┴ └────┘ └──────────┘ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ └────┘ └──────────┘ ┴ ┴┴ ┴ ┴┴ ┴ ┴┴
1609 begin
st └─────
1610 rw [revzip, powerset_aux_eq_map_coe, ← map_reverse, zip_map, ← revzip] at h,
id └────┘ └─────────────────────┘ └─────────┘ └─────┘ └────┘
src └──┘└────┘└┘└─────────────────────┘└──┘└─────────┘└┘└─────┘└──┘└────┘└────┘
typ └──┘└────┘└┘└─────────────────────┘└──┘└─────────┘└┘└─────┘└──┘└────┘└────┘
doc └──┘ └┘ └──┘ └┘ └──┘ └────┘
txt └──┘ └┘ └──┘ └┘ └──┘ └────┘
par └──┘ └┘ └──┘ └┘ └──┘ └────┘
pid └┘ └┘ └──┘ └┘ └──┘ ┴└───┘
st ───────────┘└───────────────────────┘└─────────────┘└───────┘└────────┘┴└───┘└─
1611 simp at h, rcases h with ⟨l₁, l₂, h, rfl, rfl⟩,
id ┴
src └───────┘ └─────┘ └─────────────────────────┘
typ └───────┘ └─────┘┴└─────────────────────────┘
doc └───────┘ └─────┘ └─────────────────────────┘
txt └───────┘ └─────┘ └─────────────────────────┘
par └───────┘ └─────┘ └─────────────────────────┘
pid ┴└──┘ ┴ └─────────────────────────┘
st ──────────┘└───────────────────────────────────┘└─
1612 exact quot.sound (revzip_sublists _ _ _ h)
id └────────┘ └─────────────┘ ┴
src └────┘└────────┘┴ └─────────────┘└─────┘ └┘
typ └────┘└────────┘┴ └─────────────┘└─────┘┴└┘
doc └────┘ ┴ └─────┘ └┘
txt └────┘ ┴ └─────┘ └┘
par └────┘ ┴ └─────┘ └┘
pid ┴ ┴ └─────┘ ┴┴
st ────────────────────────────────────────────┘
1613 end
st └─┘
1614
1615 theorem revzip_powerset_aux' {l : list α} ⦃x⦄
id └──┘ ┴
src └──┘
typ └──┘ ┴
1616 (h : x ∈ revzip (powerset_aux' l)) : x.1 + x.2 = ↑l :=
id ┴ ┴ └────┘ └───────────┘ ┴ ┴┴ ┴ ┴┴ ┴ ┴┴
src ┴ └────┘ └───────────┘ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ └────┘ └───────────┘ ┴ ┴┴ ┴ ┴┴ ┴ ┴┴
1617 begin
st └─────
1618 rw [revzip, powerset_aux', ← map_reverse, zip_map, ← revzip] at h,
id └────┘ └───────────┘ └─────────┘ └─────┘ └────┘
src └──┘└────┘└┘└───────────┘└──┘└─────────┘└┘└─────┘└──┘└────┘└────┘
typ └──┘└────┘└┘└───────────┘└──┘└─────────┘└┘└─────┘└──┘└────┘└────┘
doc └──┘ └┘ └──┘ └┘ └──┘ └────┘
txt └──┘ └┘ └──┘ └┘ └──┘ └────┘
par └──┘ └┘ └──┘ └┘ └──┘ └────┘
pid └┘ └┘ └──┘ └┘ └──┘ ┴└───┘
st ───────────┘└─────────────┘└─────────────┘└───────┘└────────┘┴└───┘└─
1619 simp at h, rcases h with ⟨l₁, l₂, h, rfl, rfl⟩,
id ┴
src └───────┘ └─────┘ └─────────────────────────┘
typ └───────┘ └─────┘┴└─────────────────────────┘
doc └───────┘ └─────┘ └─────────────────────────┘
txt └───────┘ └─────┘ └─────────────────────────┘
par └───────┘ └─────┘ └─────────────────────────┘
pid ┴└──┘ ┴ └─────────────────────────┘
st ──────────┘└───────────────────────────────────┘└─
1620 exact quot.sound (revzip_sublists' _ _ _ h)
id └────────┘ └──────────────┘ ┴
src └────┘└────────┘┴ └──────────────┘└─────┘ └┘
typ └────┘└────────┘┴ └──────────────┘└─────┘┴└┘
doc └────┘ ┴ └─────┘ └┘
txt └────┘ ┴ └─────┘ └┘
par └────┘ ┴ └─────┘ └┘
pid ┴ ┴ └─────┘ ┴┴
st ─────────────────────────────────────────────┘
1621 end
st └─┘
1622
1623 theorem revzip_powerset_aux_lemma [decidable_eq α] (l : list α)
id └──────────┘ ┴ └──┘ ┴
src └──────────┘ └──┘
typ └──────────┘ ┴ └──┘ ┴
1624 {l' : list (multiset α)} (H : ∀ ⦃x : _ × _⦄, x ∈ revzip l' → x.1 + x.2 = ↑l) :
id └──┘ └──────┘ ┴ ┴ ┴ ┴ └────┘ └┘ ┴┴ ┴ ┴┴ ┴ ┴┴
src └──┘ └──────┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴
typ └──┘ └──────┘ ┴ ┴ ┴ ┴ └────┘ └┘ ┴┴ ┴ ┴┴ ┴ ┴┴
doc └──────┘
1625 revzip l' = l'.map (λ x, (x, ↑l - x)) :=
id └────┘ └┘ ┴ └┘└──┘ ┴ ┴┴ ┴┴ ┴ ┴
src └────┘ ┴ └──┘ ┴ ┴ ┴
typ └────┘ └┘ ┴ └┘└──┘ ┴ ┴┴ ┴┴ ┴ ┴
1626 begin
st └─────
1627 have : forall₂ (λ (p : multiset α × multiset α) (s : multiset α), p = (s, ↑l - s))
id └─────┘ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴┴ ┴
src └─────┘└─────┘┴ └────┘ ┴ ┴┴┴ ┴ └─────┘└──────┘┴ └─┘ ┴┴┴┴ └┘┴ ┴┴┴ └──
typ └─────┘└─────┘┴ └────┘└──────┘┴ ┴┴┴ ┴ └─────┘└──────┘┴┴└─┘ ┴┴┴┴ └┘┴┴┴┴┴ └──
doc └─────┘ ┴ └────┘ ┴ ┴ ┴ ┴ └─────┘└──────┘┴ └─┘ ┴ ┴ └┘ ┴ ┴ └──
txt └─────┘ ┴ └────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ └─┘ ┴ ┴ └┘ ┴ ┴ └──
par └─────┘ ┴ └────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ └─┘ ┴ ┴ └┘ ┴ ┴ └──
pid └───┘└┘ ┴ └────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ └─┘ ┴ ┴ └┘ ┴ ┴ └──
st ─────────────────────────────────────────────────────────────────────────────────────
1628 (revzip l') ((revzip l').map prod.fst),
id └────┘ └┘ └──────┘
src ───┘ ┴ └┘ └────┘┴ └────┘└──────┘┴
typ ───┘ ┴ └┘ └────┘┴└┘└────┘└──────┘┴
doc ───┘ ┴ └┘ ┴ └────┘ ┴
txt ───┘ ┴ └┘ ┴ └────┘ ┴
par ───┘ ┴ └┘ ┴ └────┘ ┴
pid ───┘ ┴ └┘ ┴ └────┘ ┴
st ─────────────────────────────────────────┘└─
1629 { rw forall₂_map_right_iff,
id └───────────────────┘
src └─┘└───────────────────┘
typ └─┘└───────────────────┘
doc └─┘
txt └─┘
par └─┘
pid ┴
st ───┘└──────────────────────┘└─
1630 apply forall₂_same, rintro ⟨s, t⟩ h,
id └──────────┘
src └────┘└──────────┘ └─────────────┘
typ └────┘└──────────┘ └─────────────┘
doc └────┘ └─────────────┘
txt └────┘ └─────────────┘
par └────┘ └─────────────┘
pid ┴ └───────┘
st ─────────────────────┘└───────────────┘└─
1631 dsimp, rw [← H h, add_sub_cancel_left] },
id ┴ ┴ └─────────────────┘
src └───┘ └────┘ ┴ └┘└─────────────────┘└┘
typ └───┘ └────┘┴┴┴└┘└─────────────────┘└┘
doc └───┘ └────┘ ┴ └┘ └┘
txt └───┘ └────┘ ┴ └┘ └┘
par └───┘ └────┘ ┴ └┘ └┘
pid └──┘ ┴ └┘ ┴┴
st ────────┘└─────────┘└───────────────────┘┴┴└┘└
1632 rw [← forall₂_eq_eq_eq, forall₂_map_right_iff], simpa
id └──────────────┘ └───────────────────┘
src └────┘└──────────────┘└┘└───────────────────┘┴ └────┘
typ └────┘└──────────────┘└┘└───────────────────┘┴ └────┘
doc └────┘ └┘ ┴ └────┘
txt └────┘ └┘ ┴ └────┘
par └────┘ └┘ ┴ └────┘
pid └──┘ └┘ ┴ ┴
st ───────────────────────┘└─────────────────────┘└───────┘
1633 end
st └─┘
1634
1635 theorem revzip_powerset_aux_perm_aux' {l : list α} :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1636 revzip (powerset_aux l) ~ revzip (powerset_aux' l) :=
id └────┘ └──────────┘ ┴ ┴ └────┘ └───────────┘ ┴
src └────┘ └──────────┘ ┴ └────┘ └───────────┘
typ └────┘ └──────────┘ ┴ ┴ └────┘ └───────────┘ ┴
doc ┴
1637 begin
st └─────
1638 haveI := classical.dec_eq α,
id └──────────────┘ ┴
src └───────┘└──────────────┘┴
typ └───────┘└──────────────┘┴┴
doc └───────┘ ┴
txt └───────┘ ┴
par └───────┘ ┴
pid ┴└─┘ ┴
st ────────────────────────────┘└─
1639 rw [revzip_powerset_aux_lemma l revzip_powerset_aux,
id └───────────────────────┘ ┴ └─────────────────┘
src └──┘└───────────────────────┘┴ ┴└─────────────────┘└─
typ └──┘└───────────────────────┘┴┴┴└─────────────────┘└─
doc └──┘ ┴ ┴ └─
txt └──┘ ┴ ┴ └─
par └──┘ ┴ ┴ └─
pid └┘ ┴ ┴ └─
st ────────────────────────────────────────────────────┘└─
1640 revzip_powerset_aux_lemma l revzip_powerset_aux'],
id └───────────────────────┘ ┴ └──────────────────┘
src ─────┘└───────────────────────┘┴ ┴└──────────────────┘┴
typ ─────┘└───────────────────────┘┴┴┴└──────────────────┘┴
doc ─────┘ ┴ ┴ ┴
txt ─────┘ ┴ ┴ ┴
par ─────┘ ┴ ┴ ┴
pid ─────┘ ┴ ┴ ┴
st ─────────────────────────────────────────────────────┘└──
1641 exact perm_map _ powerset_aux_perm_powerset_aux',
id └──────┘ └─────────────────────────────┘
src └────┘└──────┘└─┘└─────────────────────────────┘
typ └────┘└──────┘└─┘└─────────────────────────────┘
doc └────┘ └─┘
txt └────┘ └─┘
par └────┘ └─┘
pid ┴ └─┘
st ─────────────────────────────────────────────────┘└─
1642 end
st ──┘
1643
1644 theorem revzip_powerset_aux_perm {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id └──┘ ┴ └┘ ┴ └┘
src └──┘ ┴
typ └──┘ ┴ └┘ ┴ └┘
doc ┴
1645 revzip (powerset_aux l₁) ~ revzip (powerset_aux l₂) :=
id └────┘ └──────────┘ └┘ ┴ └────┘ └──────────┘ └┘
src └────┘ └──────────┘ ┴ └────┘ └──────────┘
typ └────┘ └──────────┘ └┘ ┴ └────┘ └──────────┘ └┘
doc ┴
1646 begin
st └─────
1647 haveI := classical.dec_eq α,
id └──────────────┘ ┴
src └───────┘└──────────────┘┴
typ └───────┘└──────────────┘┴┴
doc └───────┘ ┴
txt └───────┘ ┴
par └───────┘ ┴
pid ┴└─┘ ┴
st ────────────────────────────┘└─
1648 simp [λ l:list α, revzip_powerset_aux_lemma l revzip_powerset_aux, coe_eq_coe.2 p],
id └──┘ ┴ └───────────────────────┘ └─────────────────┘ └────────┘ ┴
src └────┘ └─┘└──┘┴ └┘└───────────────────────┘┴ ┴└─────────────────┘└┘└────────┘└─┘ ┴
typ └────┘ └─┘└──┘┴┴└┘└───────────────────────┘┴ ┴└─────────────────┘└┘└────────┘└─┘┴┴
doc └────┘ └─┘ ┴ └┘ ┴ ┴ └┘ └─┘ ┴
txt └────┘ └─┘ ┴ └┘ ┴ ┴ └┘ └─┘ ┴
par └────┘ └─┘ ┴ └┘ ┴ ┴ └┘ └─┘ ┴
pid ┴┴ └─┘ ┴ └┘ ┴ ┴ └┘ └─┘ ┴
st ───────────────────────────────────────────────────────────────────────────────────┘└─
1649 exact perm_map _ (powerset_aux_perm p)
id └──────┘ └───────────────┘ ┴
src └────┘└──────┘└─┘ └───────────────┘┴ └┘
typ └────┘└──────┘└─┘ └───────────────┘┴┴└┘
doc └────┘ └─┘ ┴ └┘
txt └────┘ └─┘ ┴ └┘
par └────┘ └─┘ ┴ └┘
pid ┴ └─┘ ┴ ┴┴
st ────────────────────────────────────────┘
1650 end
st └─┘
1651
1652 /-- The antidiagonal of a multiset `s` consists of all pairs `(t₁, t₂)`
1653 such that `t₁ + t₂ = s`. These pairs are counted with multiplicities. -/
1654 def antidiagonal (s : multiset α) : multiset (multiset α × multiset α) :=
id └──────┘ ┴ └──────┘ └──────┘ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘ └──────┘ ┴ └──────┘
typ └──────┘ ┴ └──────┘ └──────┘ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘ └──────┘
1655 quot.lift_on s
id └──────────┘ ┴
src └──────────┘
typ └──────────┘ ┴
1656 (λ l, (revzip (powerset_aux l) : multiset (multiset α × multiset α)))
id ┴ └────┘ └──────────┘ ┴ └──────┘ └──────┘ ┴ ┴ └──────┘ ┴
src └────┘ └──────────┘ └──────┘ └──────┘ ┴ └──────┘
typ ┴ └────┘ └──────────┘ ┴ └──────┘ └──────┘ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘
1657 (λ l₁ l₂ h, quot.sound (revzip_powerset_aux_perm h))
id └┘ └┘ ┴ └────────┘ └──────────────────────┘ ┴
src └────────┘ └──────────────────────┘
typ └┘ └┘ ┴ └────────┘ └──────────────────────┘ ┴
1658
1659 theorem antidiagonal_coe (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1660 @antidiagonal α l = revzip (powerset_aux l) := rfl
id └──────────┘ ┴ ┴ ┴ └────┘ └──────────┘ ┴ └─┘
src └──────────┘ ┴ └────┘ └──────────┘ └─┘
typ └──────────┘ ┴ ┴ ┴ └────┘ └──────────┘ ┴ └─┘
doc └──────────┘
1661
1662 @[simp] theorem antidiagonal_coe' (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
doc └──┘
1663 @antidiagonal α l = revzip (powerset_aux' l) :=
id └──────────┘ ┴ ┴ ┴ └────┘ └───────────┘ ┴
src └──────────┘ ┴ └────┘ └───────────┘
typ └──────────┘ ┴ ┴ ┴ └────┘ └───────────┘ ┴
doc └──────────┘
1664 quot.sound revzip_powerset_aux_perm_aux'
id └────────┘ └───────────────────────────┘
src └────────┘ └───────────────────────────┘
typ └────────┘ └───────────────────────────┘
1665
1666 /-- A pair `(t₁, t₂)` of multisets is contained in `antidiagonal s`
1667 if and only if `t₁ + t₂ = s`. -/
1668 @[simp] theorem mem_antidiagonal {s : multiset α} {x : multiset α × multiset α} :
id └──────┘ ┴ └──────┘ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘ ┴ └──────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘ └──────┘
1669 x ∈ antidiagonal s ↔ x.1 + x.2 = s :=
id ┴ ┴ └──────────┘ ┴ ┴ ┴┴ ┴ ┴┴ ┴ ┴
src ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ └──────────┘ ┴ ┴ ┴┴ ┴ ┴┴ ┴ ┴
doc └──────────┘
1670 quotient.induction_on s $ λ l, begin
id └───────────────────┘ ┴ ┴
src └───────────────────┘
typ └───────────────────┘ ┴ ┴
st └─────
1671 simp [antidiagonal_coe], refine ⟨λ h, revzip_powerset_aux h, λ h, _⟩,
id └──────────────┘ └─────────────────┘
src └────┘└──────────────┘┴ └─────┘ └──┘└─────────────────┘┴ └┘ └────┘
typ └────┘└──────────────┘┴ └─────┘ └──┘└─────────────────┘┴ └┘ └────┘
doc └────┘ ┴ └─────┘ └──┘ ┴ └┘ └────┘
txt └────┘ ┴ └─────┘ └──┘ ┴ └┘ └────┘
par └────┘ ┴ └─────┘ └──┘ ┴ └┘ └────┘
pid ┴┴ ┴ ┴ └──┘ ┴ └┘ └────┘
st ────────────────────────┘└───────────────────────────────────────────┘└─
1672 haveI := classical.dec_eq α,
id └──────────────┘ ┴
src └───────┘└──────────────┘┴
typ └───────┘└──────────────┘┴┴
doc └───────┘ ┴
txt └───────┘ ┴
par └───────┘ ┴
pid ┴└─┘ ┴
st ────────────────────────────┘└─
1673 simp [revzip_powerset_aux_lemma l revzip_powerset_aux, h.symm],
id └───────────────────────┘ ┴ └─────────────────┘
src └────┘└───────────────────────┘┴ ┴└─────────────────┘└┘ ┴
typ └────┘└───────────────────────┘┴┴┴└─────────────────┘└┘└────┘┴
doc └────┘ ┴ ┴ └┘ ┴
txt └────┘ ┴ ┴ └┘ ┴
par └────┘ ┴ ┴ └┘ ┴
pid ┴┴ ┴ ┴ └┘ ┴
st ───────────────────────────────────────────────────────────────┘└─
1674 cases x with x₁ x₂,
id ┴
src └────┘ └─────────┘
typ └────┘┴└─────────┘
doc └────┘ └─────────┘
txt └────┘ └─────────┘
par └────┘ └─────────┘
pid ┴ └─────────┘
st ───────────────────┘└─
1675 exact ⟨_, le_add_right _ _, by rw add_sub_cancel_left _ _⟩
id └──────────┘ └─────────────────┘
src └────┘ └─┘└──────────┘└────┘ ┴└─┘└─────────────────┘└──┘└┘
typ └────┘ └─┘└──────────┘└────┘ ┴└─┘└─────────────────┘└──┘└┘
doc └────┘ └─┘ └────┘ ┴└─┘ └──┘└┘
txt └────┘ └─┘ └────┘ ┴└─┘ └──┘└┘
par └────┘ └─┘ └────┘ ┴└─┘ └──┘└┘
pid ┴ └─┘ └────┘ └──┘ └───┘┴
st ───────────────────────────────┘└─────────────────────────┘└┘
1676 end
st └─┘
1677
1678 @[simp] theorem antidiagonal_map_fst (s : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1679 (antidiagonal s).map prod.fst = powerset s :=
id └──────────┘ ┴ └─┘ └──────┘ ┴ └──────┘ ┴
src └──────────┘ └─┘ └──────┘ ┴ └──────┘
typ └──────────┘ ┴ └─┘ └──────┘ ┴ └──────┘ ┴
doc └──────────┘ └─┘
1680 quotient.induction_on s $ λ l,
id └───────────────────┘ ┴ ┴
src └───────────────────┘
typ └───────────────────┘ ┴ ┴
1681 by simp [powerset_aux']
id └───────────┘
src └────┘└───────────┘└─
typ └────┘└───────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────────────────
1682
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1683 @[simp] theorem antidiagonal_map_snd (s : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1684 (antidiagonal s).map prod.snd = powerset s :=
id └──────────┘ ┴ └─┘ └──────┘ ┴ └──────┘ ┴
src └──────────┘ └─┘ └──────┘ ┴ └──────┘
typ └──────────┘ ┴ └─┘ └──────┘ ┴ └──────┘ ┴
doc └──────────┘ └─┘
1685 quotient.induction_on s $ λ l,
id └───────────────────┘ ┴ ┴
src └───────────────────┘
typ └───────────────────┘ ┴ ┴
1686 by simp [powerset_aux']
id └───────────┘
src └────┘└───────────┘└─
typ └────┘└───────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────────────────
1687
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1688 @[simp] theorem antidiagonal_zero : @antidiagonal α 0 = (0, 0)::0 := rfl
id └──────────┘ ┴ ┴ ┴ └┘ └─┘
src └──────────┘ ┴ ┴ └┘ └─┘
typ └──────────┘ ┴ ┴ ┴ └┘ └─┘
doc └──┘ └──────────┘ └┘
1689
1690 @[simp] theorem antidiagonal_cons (a : α) (s) : antidiagonal (a::s) =
id ┴ └──────────┘ ┴└┘┴ ┴
src └──────────┘ └┘ ┴
typ ┴ └──────────┘ ┴└┘┴ ┴
doc └──┘ └──────────┘ └┘
1691 map (prod.map id (cons a)) (antidiagonal s) +
id └─┘ └──────┘ └┘ └──┘ ┴ └──────────┘ ┴ ┴
src └─┘ └──────┘ └┘ └──┘ └──────────┘ ┴
typ └─┘ └──────┘ └┘ └──┘ ┴ └──────────┘ ┴ ┴
doc └─┘ └──┘ └──────────┘
1692 map (prod.map (cons a) id) (antidiagonal s) :=
id └─┘ └──────┘ └──┘ ┴ └┘ └──────────┘ ┴
src └─┘ └──────┘ └──┘ └┘ └──────────┘
typ └─┘ └──────┘ └──┘ ┴ └┘ └──────────┘ ┴
doc └─┘ └──┘ └──────────┘
1693 quotient.induction_on s $ λ l, begin
id └───────────────────┘ ┴ ┴
src └───────────────────┘
typ └───────────────────┘ ┴ ┴
st └─────
1694 simp [revzip, reverse_append],
id └────┘ └────────────┘
src └────┘└────┘└┘└────────────┘┴
typ └────┘└────┘└┘└────────────┘┴
doc └────┘ └┘ ┴
txt └────┘ └┘ ┴
par └────┘ └┘ ┴
pid ┴┴ └┘ ┴
st ──────────────────────────────┘└─
1695 rw [← zip_map, ← zip_map, zip_append, (_ : _++_=_)],
id └─────┘ └─────┘ └────────┘ └┘ ┴
src └────┘└─────┘└──┘└─────┘└┘└────────┘└┘ └───┘└┘┴┴└─┘
typ └────┘└─────┘└──┘└─────┘└┘└────────┘└┘ └───┘└┘┴┴└─┘
doc └────┘ └──┘ └┘ └┘ └───┘ ┴ └─┘
txt └────┘ └──┘ └┘ └┘ └───┘ ┴ └─┘
par └────┘ └──┘ └┘ └┘ └───┘ ┴ └─┘
pid └──┘ └──┘ └┘ └┘ └───┘ ┴ └─┘
st ──────────────┘└─────────┘└──────────┘└────────────┘└──
1696 {congr; simp}, {simp}
src └───┘ └──┘ └──┘
typ └───┘ └──┘ └──┘
doc └──┘ └──┘
txt └───┘ └──┘ └──┘
par └───┘ └──┘ └──┘
st ─────────────┘└┘└────┘└─
1697 end
st ──┘
1698
1699 @[simp] theorem card_antidiagonal (s : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1700 card (antidiagonal s) = 2 ^ card s :=
id └──┘ └──────────┘ ┴ ┴ ┴ └──┘ ┴
src └──┘ └──────────┘ ┴ ┴ └──┘
typ └──┘ └──────────┘ ┴ ┴ ┴ └──┘ ┴
doc └──┘ └──────────┘ └──┘
1701 by have := card_powerset s;
id └───────────┘ ┴
src └──────┘└───────────┘┴
typ └──────┘└───────────┘┴┴
doc └──────┘ ┴
txt └──────┘ ┴
par └──────┘ ┴
pid └───┘└─┘ ┴
st └─────────────────────────
1702 rwa [← antidiagonal_map_fst, card_map] at this
id └──────────────────┘ └──────┘
src └─────┘└──────────────────┘└┘└──────┘└─────────
typ └─────┘└──────────────────┘└┘└──────┘└─────────
doc └─────┘ └┘ └─────────
txt └─────┘ └┘ └─────────
par └─────┘ └┘ └─────────
pid └──┘ └┘ ┴└──────┘└
st ───────┘└────────────────────┘└────────┘┴└────────
1703
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1704 lemma prod_map_add [comm_semiring β] {s : multiset α} {f g : α → β} :
id └───────────┘ ┴ └──────┘ ┴ ┴ ┴
src └───────────┘ └──────┘
typ └───────────┘ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘
1705 prod (s.map (λa, f a + g a)) =
id └──┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──┘ └──┘ ┴ ┴
typ └──┘ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──┘
1706 sum ((antidiagonal s).map (λp, (p.1.map f).prod * (p.2.map g).prod)) :=
id └─┘ └──────────┘ ┴ └─┘ ┴ ┴┴ └─┘ ┴ └──┘ ┴ ┴┴ └─┘ ┴ └──┘
src └─┘ └──────────┘ └─┘ ┴ └─┘ └──┘ ┴ ┴ └─┘ └──┘
typ └─┘ └──────────┘ ┴ └─┘ ┴ ┴┴ └─┘ ┴ └──┘ ┴ ┴┴ └─┘ ┴ └──┘
doc └──────────┘ └─┘ └─┘ └──┘ └─┘ └──┘
1707 begin
st └─────
1708 refine s.induction_on _ _,
id └────────────┘
src └─────┘└────────────┘└──┘
typ └─────┘└────────────┘└──┘
doc └─────┘ └──┘
txt └─────┘ └──┘
par └─────┘ └──┘
pid ┴ └──┘
st ──────────────────────────┘└─
1709 { simp },
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
pid ┴
st ───┘└───┘└┘└
1710 { assume a s ih, simp [ih, add_mul, mul_comm, mul_left_comm, mul_assoc, sum_map_mul_left.symm] },
id └┘ └─────┘ └──────┘ └───────────┘ └───────┘
src └───────────┘ └────┘ └┘└─────┘└┘└──────┘└┘└───────────┘└┘└───────┘└┘ └┘
typ └───────────┘ └────┘└┘└┘└─────┘└┘└──────┘└┘└───────────┘└┘└───────┘└┘└───────────────────┘└┘
doc └───────────┘ └────┘ └┘ └┘ └┘ └┘ └┘ └┘
txt └───────────┘ └────┘ └┘ └┘ └┘ └┘ └┘ └┘
par └───────────┘ └────┘ └┘ └┘ └┘ └┘ └┘ └┘
pid └───────────┘ ┴┴ └┘ └┘ └┘ └┘ └┘ ┴┴
st ────────────────┘└──────────────────────────────────────────────────────────────────────────────┘└──
1711 end
st ──┘
1712
1713 /- powerset_len -/
1714
1715 def powerset_len_aux (n : ℕ) (l : list α) : list (multiset α) :=
id ┴ └──┘ ┴ └──┘ └──────┘ ┴
src ┴ └──┘ └──┘ └──────┘
typ ┴ └──┘ ┴ └──┘ └──────┘ ┴
doc └──────┘
1716 sublists_len_aux n l coe []
id └──────────────┘ ┴ ┴ └─┘ └┘
src └──────────────┘ └─┘ └┘
typ └──────────────┘ ┴ ┴ └─┘ └┘
1717
1718 theorem powerset_len_aux_eq_map_coe {n} {l : list α} :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1719 powerset_len_aux n l = (sublists_len n l).map coe :=
id └──────────────┘ ┴ ┴ ┴ └──────────┘ ┴ ┴ └─┘ └─┘
src └──────────────┘ ┴ └──────────┘ └─┘ └─┘
typ └──────────────┘ ┴ ┴ ┴ └──────────┘ ┴ ┴ └─┘ └─┘
1720 by rw [powerset_len_aux, sublists_len_aux_eq, append_nil]
id └──────────────┘ └─────────────────┘ └────────┘
src └──┘└──────────────┘└┘└─────────────────┘└┘└────────┘└─
typ └──┘└──────────────┘└┘└─────────────────┘└┘└────────┘└─
doc └──┘ └┘ └┘ └─
txt └──┘ └┘ └┘ └─
par └──┘ └┘ └┘ └─
pid └┘ └┘ └┘ ┴└
st └───────────────────┘└───────────────────┘└──────────┘┴└
1721
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1722 @[simp] theorem mem_powerset_len_aux {n} {l : list α} {s} :
id └──┘ ┴
src └──┘
typ └──┘ ┴
doc └──┘
1723 s ∈ powerset_len_aux n l ↔ s ≤ ↑l ∧ card s = n :=
id ┴ ┴ └──────────────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ └──┘ ┴ ┴ ┴
src ┴ └──────────────┘ ┴ ┴ ┴ ┴ └──┘ ┴
typ ┴ ┴ └──────────────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ └──┘ ┴ ┴ ┴
doc └──┘
1724 quotient.induction_on s $
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
1725 by simp [powerset_len_aux_eq_map_coe, subperm]; exact
id └─────────────────────────┘ └─────┘
src └────┘└─────────────────────────┘└┘└─────┘┴ └─────
typ └────┘└─────────────────────────┘└┘└─────┘┴ └─────
doc └────┘ └┘└─────┘┴ └─────
txt └────┘ └┘ ┴ └─────
par └────┘ └┘ ┴ └─────
pid ┴┴ └┘ ┴ └
st └───────────────────────────────────────────────────
1726 λ l₁, ⟨λ ⟨l₂, ⟨s, e⟩, p⟩, ⟨⟨_, p, s⟩, (perm_length p.symm).trans e⟩,
id ┴ ┴ ┴ └───┘
src ─┘ └───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ └─┘ ┴ └───┘└──────┘ └──
typ ─┘ └───┘ └┘ └┘ ┴└┘┴└─┘┴└─┘ └─┘ └┘ └─┘ ┴ └───┘└──────┘ └──
doc ─┘ └───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ └─┘ ┴ └──────┘ └──
txt ─┘ └───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ └─┘ ┴ └──────┘ └──
par ─┘ └───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ └─┘ ┴ └──────┘ └──
pid ─┘ └───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ └─┘ ┴ └──────┘ └──
st ───────────────────────────────────────────────────────────────────────
1727 λ ⟨⟨l₂, p, s⟩, e⟩, ⟨_, ⟨s, (perm_length p).trans e⟩, p⟩⟩
id ┴ ┴ ┴ └─────────┘
src ───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ └─────────┘┴ └──────┘ └─┘ └──
typ ───┘ └┘ └┘┴└┘┴└─┘┴└─┘ └─┘ └┘ └─────────┘┴ └──────┘ └─┘ └──
doc ───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ ┴ └──────┘ └─┘ └──
txt ───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ ┴ └──────┘ └─┘ └──
par ───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ ┴ └──────┘ └─┘ └──
pid ───┘ └┘ └┘ └┘ └─┘ └─┘ └─┘ └┘ ┴ └──────┘ └─┘ └┘└
st ─────────────────────────────────────────────────────────────
1728
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1729 @[simp] theorem powerset_len_aux_zero (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
doc └──┘
1730 powerset_len_aux 0 l = [0] :=
id └──────────────┘ ┴ ┴ ┴ ┴
src └──────────────┘ ┴ ┴ ┴
typ └──────────────┘ ┴ ┴ ┴ ┴
1731 by simp [powerset_len_aux_eq_map_coe]
id └─────────────────────────┘
src └────┘└─────────────────────────┘└─
typ └────┘└─────────────────────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └───────────────────────────────────
1732
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1733 @[simp] theorem powerset_len_aux_nil (n : ℕ) :
id ┴
src ┴
typ ┴
doc └──┘
1734 powerset_len_aux (n+1) (@nil α) = [] := rfl
id └──────────────┘ ┴┴ └─┘ ┴ ┴ └┘ └─┘
src └──────────────┘ ┴ └─┘ ┴ └┘ └─┘
typ └──────────────┘ ┴┴ └─┘ ┴ ┴ └┘ └─┘
1735
1736 @[simp] theorem powerset_len_aux_cons (n : ℕ) (a : α) (l : list α) :
id ┴ ┴ └──┘ ┴
src ┴ └──┘
typ ┴ ┴ └──┘ ┴
doc └──┘
1737 powerset_len_aux (n+1) (a::l) =
id └──────────────┘ ┴┴ ┴└┘┴ ┴
src └──────────────┘ ┴ └┘ ┴
typ └──────────────┘ ┴┴ ┴└┘┴ ┴
1738 powerset_len_aux (n+1) l ++ list.map (cons a) (powerset_len_aux n l) :=
id └──────────────┘ ┴┴ ┴ └┘ └──────┘ └──┘ ┴ └──────────────┘ ┴ ┴
src └──────────────┘ ┴ └┘ └──────┘ └──┘ └──────────────┘
typ └──────────────┘ ┴┴ ┴ └┘ └──────┘ └──┘ ┴ └──────────────┘ ┴ ┴
doc └──┘
1739 by simp [powerset_len_aux_eq_map_coe]; refl
id └─────────────────────────┘
src └────┘└─────────────────────────┘┴ └────
typ └────┘└─────────────────────────┘┴ └────
doc └────┘ ┴ └────
txt └────┘ ┴ └────
par └────┘ ┴ └────
pid ┴┴ ┴ └
st └─────────────────────────────────────────
1740
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1741 theorem powerset_len_aux_perm {n} {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id └──┘ ┴ └┘ ┴ └┘
src └──┘ ┴
typ └──┘ ┴ └┘ ┴ └┘
doc ┴
1742 powerset_len_aux n l₁ ~ powerset_len_aux n l₂ :=
id └──────────────┘ ┴ └┘ ┴ └──────────────┘ ┴ └┘
src └──────────────┘ ┴ └──────────────┘
typ └──────────────┘ ┴ └┘ ┴ └──────────────┘ ┴ └┘
doc ┴
1743 begin
st └─────
1744 induction n with n IHn generalizing l₁ l₂, {simp},
id ┴
src └────────┘ └────────────────────────────┘ └──┘
typ └────────┘┴└────────────────────────────┘ └──┘
doc └────────┘ └────────────────────────────┘ └──┘
txt └────────┘ └────────────────────────────┘ └──┘
par └────────┘ └────────────────────────────┘ └──┘
pid ┴ ┴└────────┘└─────────────────┘
st ──────────────────────────────────────────┘└─────┘└┘└
1745 induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {refl},
id ┴
src └────────┘ └─────────────────────────────────────────────┘ └──┘
typ └────────┘┴└─────────────────────────────────────────────┘ └──┘
doc └────────┘ └─────────────────────────────────────────────┘ └──┘
txt └────────┘ └─────────────────────────────────────────────┘ └──┘
par └────────┘ └─────────────────────────────────────────────┘ └──┘
pid ┴ ┴└────────────────────────────────────────────┘
st ───────────────────────────────────────────────────────────┘└─────┘└┘└
1746 { simp, exact perm_app IH (perm_map _ (IHn p)) },
id └──────┘ └┘ └──────┘ └─┘ ┴
src └──┘ └────┘└──────┘┴ ┴ └──────┘└─┘ ┴ └─┘
typ └──┘ └────┘└──────┘┴└┘┴ └──────┘└─┘ └─┘┴┴└─┘
doc └──┘ └────┘ ┴ ┴ └─┘ ┴ └─┘
txt └──┘ └────┘ ┴ ┴ └─┘ ┴ └─┘
par └──┘ └────┘ ┴ ┴ └─┘ ┴ └─┘
pid ┴ ┴ ┴ └─┘ ┴ └┘┴
st ───┘└──┘└───────────────────────────────────────┘└┘└
1747 { simp, apply perm_app_right,
id └────────────┘
src └──┘ └────┘└────────────┘
typ └──┘ └────┘└────────────┘
doc └──┘ └────┘
txt └──┘ └────┘
par └──┘ └────┘
pid ┴
st ───┘└──┘└────────────────────┘└─
1748 cases n, {simp, apply perm.swap},
id ┴ └───────┘
src └────┘ └──┘ └────┘└───────┘
typ └────┘┴ └──┘ └────┘└───────┘
doc └────┘ └──┘ └────┘
txt └────┘ └──┘ └────┘
par └────┘ └──┘ └────┘
pid ┴ ┴
st ──────────┘└─────┘└───────────────┘└┘└
1749 simp,
src └──┘
typ └──┘
doc └──┘
txt └──┘
par └──┘
st ───────┘└─
1750 rw [← append_assoc, ← append_assoc,
id └──────────┘ └──────────┘
src └────┘└──────────┘└──┘└──────────┘└─
typ └────┘└──────────┘└──┘└──────────┘└─
doc └────┘ └──┘ └─
txt └────┘ └──┘ └─
par └────┘ └──┘ └─
pid └──┘ └──┘ └─
st ─────────────────────┘└──────────────┘└─
1751 (by funext s; simp [cons_swap] : cons b ∘ cons a = cons a ∘ cons b)],
id └───────┘ ┴ ┴ ┴ └──┘ ┴
src ───────┘ ┴└──────┘└┘└────┘└───────┘└┘└┘ ┴ ┴┴┴ ┴ ┴┴┴ ┴ ┴ ┴└──┘┴ └┘
typ ───────┘ ┴└──────┘└┘└────┘└───────┘└┘└┘ ┴ ┴┴┴ ┴ ┴┴┴ ┴┴┴ ┴└──┘┴┴└┘
doc ───────┘ ┴└──────┘└┘└────┘ └┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└──┘┴ └┘
txt ───────┘ ┴└──────┘└┘└────┘ └┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
par ───────┘ ┴└──────┘└┘└────┘ └┘└┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
pid ───────┘ └───────────────┘ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
st ──────────┘└──────────────────────────┘└──────────────────────────────────┘┴└─
1752 exact perm_app_left _ perm_app_comm },
id └───────────┘ └───────────┘
src └────┘└───────────┘└─┘└───────────┘┴
typ └────┘└───────────┘└─┘└───────────┘┴
doc └────┘ └─┘ ┴
txt └────┘ └─┘ ┴
par └────┘ └─┘ ┴
pid ┴ └─┘ ┴
st ───────────────────────────────────────┘└┘└
1753 { exact IH₁.trans IH₂ }
id └───────┘ └─┘
src └────┘└───────┘┴ ┴
typ └────┘└───────┘┴└─┘┴
doc └────┘ ┴ ┴
txt └────┘ ┴ ┴
par └────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────────────┘└─
1754 end
st ──┘
1755
1756 def powerset_len (n : ℕ) (s : multiset α) : multiset (multiset α) :=
id ┴ └──────┘ ┴ └──────┘ └──────┘ ┴
src ┴ └──────┘ └──────┘ └──────┘
typ ┴ └──────┘ ┴ └──────┘ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘
1757 quot.lift_on s
id └──────────┘ ┴
src └──────────┘
typ └──────────┘ ┴
1758 (λ l, (powerset_len_aux n l : multiset (multiset α)))
id ┴ └──────────────┘ ┴ ┴ └──────┘ └──────┘ ┴
src └──────────────┘ └──────┘ └──────┘
typ ┴ └──────────────┘ ┴ ┴ └──────┘ └──────┘ ┴
doc └──────┘ └──────┘
1759 (λ l₁ l₂ h, quot.sound (powerset_len_aux_perm h))
id └┘ └┘ ┴ └────────┘ └───────────────────┘ ┴
src └────────┘ └───────────────────┘
typ └┘ └┘ ┴ └────────┘ └───────────────────┘ ┴
1760
1761 theorem powerset_len_coe' (n) (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1762 @powerset_len α n l = powerset_len_aux n l := rfl
id └──────────┘ ┴ ┴ ┴ ┴ └──────────────┘ ┴ ┴ └─┘
src └──────────┘ ┴ └──────────────┘ └─┘
typ └──────────┘ ┴ ┴ ┴ ┴ └──────────────┘ ┴ ┴ └─┘
1763
1764 theorem powerset_len_coe (n) (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
1765 @powerset_len α n l = ((sublists_len n l).map coe : list (multiset α)) :=
id └──────────┘ ┴ ┴ ┴ ┴ └──────────┘ ┴ ┴ └─┘ └─┘ └──┘ └──────┘ ┴
src └──────────┘ ┴ └──────────┘ └─┘ └─┘ └──┘ └──────┘
typ └──────────┘ ┴ ┴ ┴ ┴ └──────────┘ ┴ ┴ └─┘ └─┘ └──┘ └──────┘ ┴
doc └──────┘
1766 congr_arg coe powerset_len_aux_eq_map_coe
id └───────┘ └─┘ └─────────────────────────┘
src └───────┘ └─┘ └─────────────────────────┘
typ └───────┘ └─┘ └─────────────────────────┘
1767
1768 @[simp] theorem powerset_len_zero_left (s : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
1769 powerset_len 0 s = 0::0 :=
id └──────────┘ ┴ ┴ └┘
src └──────────┘ ┴ └┘
typ └──────────┘ ┴ ┴ └┘
doc └┘
1770 quotient.induction_on s $ λ l, by simp [powerset_len_coe']; refl
id └───────────────────┘ ┴ ┴ └───────────────┘
src └───────────────────┘ └────┘└───────────────┘┴ └────
typ └───────────────────┘ ┴ ┴ └────┘└───────────────┘┴ └────
doc └────┘ ┴ └────
txt └────┘ ┴ └────
par └────┘ ┴ └────
pid ┴┴ ┴ └
st └───────────────────────────────
1771
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1772 @[simp] theorem powerset_len_zero_right (n : ℕ) :
id ┴
src ┴
typ ┴
doc └──┘
1773 @powerset_len α (n + 1) 0 = 0 := rfl
id └──────────┘ ┴ ┴ ┴ ┴ └─┘
src └──────────┘ ┴ ┴ └─┘
typ └──────────┘ ┴ ┴ ┴ ┴ └─┘
1774
1775 @[simp] theorem powerset_len_cons (n : ℕ) (a : α) (s) :
id ┴ ┴
src ┴
typ ┴ ┴
doc └──┘
1776 powerset_len (n + 1) (a::s) =
id └──────────┘ ┴ ┴ ┴└┘┴ ┴
src └──────────┘ ┴ └┘ ┴
typ └──────────┘ ┴ ┴ ┴└┘┴ ┴
doc └┘
1777 powerset_len (n + 1) s + map (cons a) (powerset_len n s) :=
id └──────────┘ ┴ ┴ ┴ ┴ └─┘ └──┘ ┴ └──────────┘ ┴ ┴
src └──────────┘ ┴ ┴ └─┘ └──┘ └──────────┘
typ └──────────┘ ┴ ┴ ┴ ┴ └─┘ └──┘ ┴ └──────────┘ ┴ ┴
doc └─┘ └──┘
1778 quotient.induction_on s $ λ l, by simp [powerset_len_coe']; refl
id └───────────────────┘ ┴ ┴ └───────────────┘
src └───────────────────┘ └────┘└───────────────┘┴ └────
typ └───────────────────┘ ┴ ┴ └────┘└───────────────┘┴ └────
doc └────┘ ┴ └────
txt └────┘ ┴ └────
par └────┘ ┴ └────
pid ┴┴ ┴ └
st └───────────────────────────────
1779
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1780 @[simp] theorem mem_powerset_len {n : ℕ} {s t : multiset α} :
id ┴ └──────┘ ┴
src ┴ └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
1781 s ∈ powerset_len n t ↔ s ≤ t ∧ card s = n :=
id ┴ ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴
src ┴ └──────────┘ ┴ ┴ ┴ └──┘ ┴
typ ┴ ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴
doc └──┘
1782 quotient.induction_on t $ λ l, by simp [powerset_len_coe']
id └───────────────────┘ ┴ ┴ └───────────────┘
src └───────────────────┘ └────┘└───────────────┘└─
typ └───────────────────┘ ┴ ┴ └────┘└───────────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────────────────────
1783
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1784 @[simp] theorem card_powerset_len (n : ℕ) (s : multiset α) :
id ┴ └──────┘ ┴
src ┴ └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
1785 card (powerset_len n s) = nat.choose (card s) n :=
id └──┘ └──────────┘ ┴ ┴ ┴ └────────┘ └──┘ ┴ ┴
src └──┘ └──────────┘ ┴ └────────┘ └──┘
typ └──┘ └──────────┘ ┴ ┴ ┴ └────────┘ └──┘ ┴ ┴
doc └──┘ └────────┘ └──┘
1786 quotient.induction_on s $ by simp [powerset_len_coe]
id └───────────────────┘ ┴ └──────────────┘
src └───────────────────┘ └────┘└──────────────┘└─
typ └───────────────────┘ ┴ └────┘└──────────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └────────────────────────
1787
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1788 theorem powerset_len_le_powerset (n : ℕ) (s : multiset α) :
id ┴ └──────┘ ┴
src ┴ └──────┘
typ ┴ └──────┘ ┴
doc └──────┘
1789 powerset_len n s ≤ powerset s :=
id └──────────┘ ┴ ┴ ┴ └──────┘ ┴
src └──────────┘ ┴ └──────┘
typ └──────────┘ ┴ ┴ ┴ └──────┘ ┴
1790 quotient.induction_on s $ λ l, by simp [powerset_len_coe]; exact
id └───────────────────┘ ┴ ┴ └──────────────┘
src └───────────────────┘ └────┘└──────────────┘┴ └─────
typ └───────────────────┘ ┴ ┴ └────┘└──────────────┘┴ └─────
doc └────┘ ┴ └─────
txt └────┘ ┴ └─────
par └────┘ ┴ └─────
pid ┴┴ ┴ └
st └───────────────────────────────
1791 subperm_of_sublist (map_sublist_map _ (sublists_len_sublist_sublists' _ _))
id └────────────────┘ └─────────────┘ └────────────────────────────┘
src ─┘└────────────────┘┴ └─────────────┘└─┘ └────────────────────────────┘└──────
typ ─┘└────────────────┘┴ └─────────────┘└─┘ └────────────────────────────┘└──────
doc ─┘ ┴ └─┘ └──────
txt ─┘ ┴ └─┘ └──────
par ─┘ ┴ └─┘ └──────
pid ─┘ ┴ └─┘ └────┘└
st ──────────────────────────────────────────────────────────────────────────────
1792
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1793 theorem powerset_len_mono (n : ℕ) {s t : multiset α} (h : s ≤ t) :
id ┴ └──────┘ ┴ ┴ ┴ ┴
src ┴ └──────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──────┘
1794 powerset_len n s ≤ powerset_len n t :=
id └──────────┘ ┴ ┴ ┴ └──────────┘ ┴ ┴
src └──────────┘ ┴ └──────────┘
typ └──────────┘ ┴ ┴ ┴ └──────────┘ ┴ ┴
1795 le_induction_on h $ λ l₁ l₂ h, by simp [powerset_len_coe]; exact
id └─────────────┘ ┴ └┘ └┘ ┴ └──────────────┘
src └─────────────┘ └────┘└──────────────┘┴ └─────
typ └─────────────┘ ┴ └┘ └┘ ┴ └────┘└──────────────┘┴ └─────
doc └────┘ ┴ └─────
txt └────┘ ┴ └─────
par └────┘ ┴ └─────
pid ┴┴ ┴ └
st └───────────────────────────────
1796 subperm_of_sublist (map_sublist_map _ (sublists_len_sublist_of_sublist _ h))
id └────────────────┘ └─────────────┘ └─────────────────────────────┘ ┴
src ─┘└────────────────┘┴ └─────────────┘└─┘ └─────────────────────────────┘└─┘ └──
typ ─┘└────────────────┘┴ └─────────────┘└─┘ └─────────────────────────────┘└─┘┴└──
doc ─┘ ┴ └─┘ └─┘ └──
txt ─┘ ┴ └─┘ └─┘ └──
par ─┘ ┴ └─┘ └─┘ └──
pid ─┘ ┴ └─┘ └─┘ └┘└
st ───────────────────────────────────────────────────────────────────────────────
1797
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
1798 /- countp -/
src ─────────────
typ ─────────────
doc ─────────────
txt ─────────────
par ─────────────
pid ─────────────
st ─────────────
1799
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1800 /-- `countp p s` counts the number of elements of `s` (with multiplicity) that
1801 satisfy `p`. -/
1802 def countp (p : α → Prop) [decidable_pred p] (s : multiset α) : ℕ :=
id ┴ └────────────┘ ┴ └──────┘ ┴ ┴
src └────────────┘ └──────┘ ┴
typ ┴ └────────────┘ ┴ └──────┘ ┴ ┴
doc └──────┘
1803 quot.lift_on s (countp p) (λ l₁ l₂, perm_countp p)
id └──────────┘ ┴ └────┘ ┴ └┘ └┘ └─────────┘ ┴
src └──────────┘ └────┘ └─────────┘
typ └──────────┘ ┴ └────┘ ┴ └┘ └┘ └─────────┘ ┴
doc └────┘
1804
1805 @[simp] theorem coe_countp (l : list α) : countp p l = l.countp p := rfl
id └──┘ ┴ └────┘ ┴ ┴ ┴ ┴└─────┘ ┴ └─┘
src └──┘ └────┘ ┴ └─────┘ └─┘
typ └──┘ ┴ └────┘ ┴ ┴ ┴ ┴└─────┘ ┴ └─┘
doc └──┘ └────┘ └─────┘
1806
1807 @[simp] theorem countp_zero (p : α → Prop) [decidable_pred p] : countp p 0 = 0 := rfl
id ┴ └────────────┘ ┴ └────┘ ┴ ┴ └─┘
src └────────────┘ └────┘ ┴ └─┘
typ ┴ └────────────┘ ┴ └────┘ ┴ ┴ └─┘
doc └──┘ └────┘
1808
1809 @[simp] theorem countp_cons_of_pos {a : α} (s) : p a → countp p (a::s) = countp p s + 1 :=
id ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ └────┘ ┴ ┴ ┴
src └────┘ └┘ ┴ └────┘ ┴
typ ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ └────┘ ┴ ┴ ┴
doc └──┘ └────┘ └┘ └────┘
1810 quot.induction_on s countp_cons_of_pos
id └───────────────┘ ┴ └────────────────┘
src └───────────────┘ └────────────────┘
typ └───────────────┘ ┴ └────────────────┘
1811
1812 @[simp] theorem countp_cons_of_neg {a : α} (s) : ¬ p a → countp p (a::s) = countp p s :=
id ┴ ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ └────┘ ┴ ┴
src ┴ └────┘ └┘ ┴ └────┘
typ ┴ ┴ ┴ ┴ └────┘ ┴ ┴└┘┴ ┴ └────┘ ┴ ┴
doc └──┘ └────┘ └┘ └────┘
1813 quot.induction_on s countp_cons_of_neg
id └───────────────┘ ┴ └────────────────┘
src └───────────────┘ └────────────────┘
typ └───────────────┘ ┴ └────────────────┘
1814
1815 theorem countp_eq_card_filter (s) : countp p s = card (filter p s) :=
id └────┘ ┴ ┴ ┴ └──┘ └────┘ ┴ ┴
src └────┘ ┴ └──┘ └────┘
typ └────┘ ┴ ┴ ┴ └──┘ └────┘ ┴ ┴
doc └────┘ └──┘ └────┘
1816 quot.induction_on s $ λ l, countp_eq_length_filter _
id └───────────────┘ ┴ ┴ └─────────────────────┘
src └───────────────┘ └─────────────────────┘
typ └───────────────┘ ┴ ┴ └─────────────────────┘
1817
1818 @[simp] theorem countp_add (s t) : countp p (s + t) = countp p s + countp p t :=
id └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └────┘ ┴ ┴ └────┘ ┴ └────┘
typ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └──┘ └────┘ └────┘ └────┘
1819 by simp [countp_eq_card_filter]
id └───────────────────┘
src └────┘└───────────────────┘└─
typ └────┘└───────────────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────────────────────────
1820
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1821 instance countp.is_add_monoid_hom : is_add_monoid_hom (countp p : multiset α → ℕ) :=
id └───────────────┘ └────┘ ┴ └──────┘ ┴ ┴
src └───────────────┘ └────┘ └──────┘ ┴
typ └───────────────┘ └────┘ ┴ └──────┘ ┴ ┴
doc └───────────────┘ └────┘ └──────┘
1822 { map_add := countp_add, map_zero := countp_zero _ }
id └────────┘ └─────────┘
src └────────┘ └─────────┘
typ └────────┘ └─────────┘
1823
1824 theorem countp_pos {s} : 0 < countp p s ↔ ∃ a ∈ s, p a :=
id ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴
src ┴ └────┘ ┴ ┴ ┴
typ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴
doc └────┘
1825 by simp [countp_eq_card_filter, card_pos_iff_exists_mem]
id └───────────────────┘ └─────────────────────┘
src └────┘└───────────────────┘└┘└─────────────────────┘└─
typ └────┘└───────────────────┘└┘└─────────────────────┘└─
doc └────┘ └┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └──────────────────────────────────────────────────────
1826
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1827 @[simp] theorem countp_sub [decidable_eq α] {s t : multiset α} (h : t ≤ s) :
id └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────────┘ └──────┘ ┴
typ └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
1828 countp p (s - t) = countp p s - countp p t :=
id └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src └────┘ ┴ ┴ └────┘ ┴ └────┘
typ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────┘ └────┘
1829 by simp [countp_eq_card_filter, h, filter_le_filter]
id └───────────────────┘ ┴ └──────────────┘
src └────┘└───────────────────┘└┘ └┘└──────────────┘└─
typ └────┘└───────────────────┘└┘┴└┘└──────────────┘└─
doc └────┘ └┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └──────────────────────────────────────────────────
1830
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1831 theorem countp_pos_of_mem {s a} (h : a ∈ s) (pa : p a) : 0 < countp p s :=
id ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
src ┴ ┴ └────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘
1832 countp_pos.2 ⟨_, h, pa⟩
id └────────┘┴ ┴ └┘
src └────────┘┴
typ └────────┘┴ ┴ └┘
1833
1834 theorem countp_le_of_le {s t} (h : s ≤ t) : countp p s ≤ countp p t :=
id ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
src ┴ └────┘ ┴ └────┘
typ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴
doc └────┘ └────┘
1835 by simpa [countp_eq_card_filter] using card_le_of_le (filter_le_filter h)
id └───────────────────┘ └───────────┘ └──────────────┘ ┴
src └─────┘└───────────────────┘└──────┘└───────────┘┴ └──────────────┘┴ └─
typ └─────┘└───────────────────┘└──────┘└───────────┘┴ └──────────────┘┴┴└─
doc └─────┘ └──────┘ ┴ ┴ └─
txt └─────┘ └──────┘ ┴ ┴ └─
par └─────┘ └──────┘ ┴ ┴ └─
pid ┴┴ ┴┴└────┘ ┴ ┴ ┴└
st └───────────────────────────────────────────────────────────────────────
1836
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1837 @[simp] theorem countp_filter {q} [decidable_pred q] (s : multiset α) :
id └────────────┘ ┴ └──────┘ ┴
src └────────────┘ └──────┘
typ └────────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
1838 countp p (filter q s) = countp (λ a, p a ∧ q a) s :=
id └────┘ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └────┘ └────┘ ┴ └────┘ ┴
typ └────┘ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └────┘ └────┘ └────┘
1839 by simp [countp_eq_card_filter]
id └───────────────────┘
src └────┘└───────────────────┘└─
typ └────┘└───────────────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────────────────────────
1840
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1841 end
1842
1843 /- count -/
1844
1845 section
1846 variable [decidable_eq α]
id └──────────┘
src └──────────┘
typ └──────────┘
1847
1848 /-- `count a s` is the multiplicity of `a` in `s`. -/
1849 def count (a : α) : multiset α → ℕ := countp (eq a)
id ┴ └──────┘ ┴ ┴ └────┘ └┘ ┴
src └──────┘ ┴ └────┘ └┘
typ ┴ └──────┘ ┴ ┴ └────┘ └┘ ┴
doc └──────┘ └────┘
1850
1851 @[simp] theorem coe_count (a : α) (l : list α) : count a (↑l) = l.count a := coe_countp _
id ┴ └──┘ ┴ └───┘ ┴ ┴┴ ┴ ┴└────┘ ┴ └────────┘
src └──┘ └───┘ ┴ ┴ └────┘ └────────┘
typ ┴ └──┘ ┴ └───┘ ┴ ┴┴ ┴ ┴└────┘ ┴ └────────┘
doc └──┘ └───┘ └────┘
1852
1853 @[simp] theorem count_zero (a : α) : count a 0 = 0 := rfl
id ┴ └───┘ ┴ ┴ └─┘
src └───┘ ┴ └─┘
typ ┴ └───┘ ┴ ┴ └─┘
doc └──┘ └───┘
1854
1855 @[simp] theorem count_cons_self (a : α) (s : multiset α) : count a (a::s) = succ (count a s) :=
id ┴ └──────┘ ┴ └───┘ ┴ ┴└┘┴ ┴ └──┘ └───┘ ┴ ┴
src └──────┘ └───┘ └┘ ┴ └──┘ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴ ┴└┘┴ ┴ └──┘ └───┘ ┴ ┴
doc └──┘ └──────┘ └───┘ └┘ └───┘
1856 countp_cons_of_pos _ rfl
id └────────────────┘ └─┘
src └────────────────┘ └─┘
typ └────────────────┘ └─┘
1857
1858 @[simp] theorem count_cons_of_ne {a b : α} (h : a ≠ b) (s : multiset α) : count a (b::s) = count a s :=
id ┴ ┴ ┴ ┴ └──────┘ ┴ └───┘ ┴ ┴└┘┴ ┴ └───┘ ┴ ┴
src ┴ └──────┘ └───┘ └┘ ┴ └───┘
typ ┴ ┴ ┴ ┴ └──────┘ ┴ └───┘ ┴ ┴└┘┴ ┴ └───┘ ┴ ┴
doc └──┘ └──────┘ └───┘ └┘ └───┘
1859 countp_cons_of_neg _ h
id └────────────────┘ ┴
src └────────────────┘
typ └────────────────┘ ┴
1860
1861 theorem count_le_of_le (a : α) {s t} : s ≤ t → count a s ≤ count a t :=
id ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
src ┴ └───┘ ┴ └───┘
typ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
doc └───┘ └───┘
1862 countp_le_of_le
id └─────────────┘
src └─────────────┘
typ └─────────────┘
1863
1864 theorem count_le_count_cons (a b : α) (s : multiset α) : count a s ≤ count a (b :: s) :=
id ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ └┘ ┴
src └──────┘ └───┘ ┴ └───┘ └┘
typ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ └┘ ┴
doc └──────┘ └───┘ └───┘ └┘
1865 count_le_of_le _ (le_cons_self _ _)
id └────────────┘ └──────────┘
src └────────────┘ └──────────┘
typ └────────────┘ └──────────┘
1866
1867 theorem count_singleton (a : α) : count a (a::0) = 1 :=
id ┴ └───┘ ┴ ┴└┘ ┴
src └───┘ └┘ ┴
typ ┴ └───┘ ┴ ┴└┘ ┴
doc └───┘ └┘
1868 by simp
src └────
typ └────
doc └────
txt └────
par └────
pid └
st └─────
1869
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1870 @[simp] theorem count_add (a : α) : ∀ s t, count a (s + t) = count a s + count a t :=
id ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
src └───┘ ┴ ┴ └───┘ ┴ └───┘
typ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
doc └──┘ └───┘ └───┘ └───┘
1871 countp_add
id └────────┘
src └────────┘
typ └────────┘
1872
1873 instance count.is_add_monoid_hom (a : α) : is_add_monoid_hom (count a : multiset α → ℕ) :=
id ┴ └───────────────┘ └───┘ ┴ └──────┘ ┴ ┴
src └───────────────┘ └───┘ └──────┘ ┴
typ ┴ └───────────────┘ └───┘ ┴ └──────┘ ┴ ┴
doc └───────────────┘ └───┘ └──────┘
1874 countp.is_add_monoid_hom
id └──────────────────────┘
src └──────────────────────┘
typ └──────────────────────┘
1875
1876 @[simp] theorem count_smul (a : α) (n s) : count a (n • s) = n * count a s :=
id ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴
src └───┘ ┴ ┴ ┴ └───┘
typ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴
doc └──┘ └───┘ └───┘
1877 by induction n; simp [*, succ_smul', succ_mul]
id ┴ └────────┘ └──────┘
src └────────┘ └───────┘└────────┘└┘└──────┘└─
typ └────────┘┴ └───────┘└────────┘└┘└──────┘└─
doc └────────┘ └───────┘ └┘ └─
txt └────────┘ └───────┘ └┘ └─
par └────────┘ └───────┘ └┘ └─
pid ┴ ┴└──┘ └┘ ┴└
st └────────────────────────────────────────────
1878
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1879 theorem count_pos {a : α} {s : multiset α} : 0 < count a s ↔ a ∈ s :=
id ┴ └──────┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └───┘ ┴ ┴
typ ┴ └──────┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └───┘
1880 by simp [count, countp_pos]
id └───┘ └────────┘
src └────┘└───┘└┘└────────┘└─
typ └────┘└───┘└┘└────────┘└─
doc └────┘└───┘└┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └─────────────────────────
1881
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1882 @[simp] theorem count_eq_zero_of_not_mem {a : α} {s : multiset α} (h : a ∉ s) : count a s = 0 :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴
src └──────┘ ┴ └───┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴
doc └──┘ └──────┘ └───┘
1883 by_contradiction $ λ h', h $ count_pos.1 (nat.pos_of_ne_zero h')
id └──────────────┘ └┘ ┴ └───────┘┴ └────────────────┘ └┘
src └──────────────┘ └───────┘┴ └────────────────┘
typ └──────────────┘ └┘ ┴ └───────┘┴ └────────────────┘ └┘
1884
1885 theorem count_eq_zero {a : α} {s : multiset α} : count a s = 0 ↔ a ∉ s :=
id ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───┘ ┴ ┴ ┴
typ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └───┘
1886 iff_not_comm.1 $ count_pos.symm.trans pos_iff_ne_zero
id └──────────┘┴ └───────┘└───┘└────┘ └─────────────┘
src └──────────┘┴ └───────┘└───┘└────┘ └─────────────┘
typ └──────────┘┴ └───────┘└───┘└────┘ └─────────────┘
1887
1888 @[simp] theorem count_repeat (a : α) (n : ℕ) : count a (repeat a n) = n :=
id ┴ ┴ └───┘ ┴ └────┘ ┴ ┴ ┴ ┴
src ┴ └───┘ └────┘ ┴
typ ┴ ┴ └───┘ ┴ └────┘ ┴ ┴ ┴ ┴
doc └──┘ └───┘ └────┘
1889 by simp [repeat]
id └────┘
src └────┘└────┘└─
typ └────┘└────┘└─
doc └────┘└────┘└─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └──────────────
1890
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1891 @[simp] theorem count_erase_self (a : α) (s : multiset α) : count a (erase s a) = pred (count a s) :=
id ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ └──┘ └───┘ ┴ ┴
src └──────┘ └───┘ └───┘ ┴ └──┘ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ └──┘ └───┘ ┴ ┴
doc └──┘ └──────┘ └───┘ └───┘ └───┘
1892 begin
st └─────
1893 by_cases a ∈ s,
id ┴ ┴ ┴
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────┘└─
1894 { rw [(by rw cons_erase h : count a s = count a (a::erase s a)),
id └────────┘ ┴ ┴ └───┘ └┘└───┘ ┴ ┴
src └──┘ └──┘└────────┘┴ └─┘ ┴ ┴ ┴┴┴└───┘┴ ┴ └┘└───┘┴ ┴ └───
typ └──┘ └──┘└────────┘┴┴└─┘ ┴ ┴ ┴┴┴└───┘┴ ┴ └┘└───┘┴┴┴┴└───
doc └──┘ └──┘ ┴ └─┘ ┴ ┴ ┴ ┴└───┘┴ ┴ └┘└───┘┴ ┴ └───
txt └──┘ └──┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───
par └──┘ └──┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───
pid └┘ └──┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───
st ───┘└─────┘└───────────────┘└───────────────────────────────────┘└─
1895 count_cons_self]; refl },
id └─────────────┘
src ───────┘└─────────────┘┴ └───┘
typ ───────┘└─────────────┘┴ └───┘
doc ───────┘ ┴ └───┘
txt ───────┘ ┴ └───┘
par ───────┘ ┴ └───┘
pid ───────┘ ┴ ┴
st ──────────────────────┘┴└─────┘└┘└
1896 { rw [erase_of_not_mem h, count_eq_zero.2 h]; refl }
id └──────────────┘ ┴ └───────────┘ ┴
src └──┘└──────────────┘┴ └┘└───────────┘└─┘ ┴ └───┘
typ └──┘└──────────────┘┴┴└┘└───────────┘└─┘┴┴ └───┘
doc └──┘ ┴ └┘ └─┘ ┴ └───┘
txt └──┘ ┴ └┘ └─┘ ┴ └───┘
par └──┘ ┴ └┘ └─┘ ┴ └───┘
pid └┘ ┴ └┘ └─┘ ┴ ┴
st ─────────────────────────┘└─────────────────┘┴└─────┘└─
1897 end
st ──┘
1898
1899 @[simp] theorem count_erase_of_ne {a b : α} (ab : a ≠ b) (s : multiset α) : count a (erase s b) = count a s :=
id ┴ ┴ ┴ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
src ┴ └──────┘ └───┘ └───┘ ┴ └───┘
typ ┴ ┴ ┴ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
doc └──┘ └──────┘ └───┘ └───┘ └───┘
1900 begin
st └─────
1901 by_cases b ∈ s,
id ┴ ┴ ┴
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────┘└─
1902 { rw [← count_cons_of_ne ab, cons_erase h] },
id └──────────────┘ └┘ └────────┘ ┴
src └────┘└──────────────┘┴ └┘└────────┘┴ └┘
typ └────┘└──────────────┘┴└┘└┘└────────┘┴┴└┘
doc └────┘ ┴ └┘ ┴ └┘
txt └────┘ ┴ └┘ ┴ └┘
par └────┘ ┴ └┘ ┴ └┘
pid └──┘ ┴ └┘ ┴ ┴┴
st ───┘└───────────────────────┘└────────────┘┴┴└┘└
1903 { rw [erase_of_not_mem h] }
id └──────────────┘ ┴
src └──┘└──────────────┘┴ └┘
typ └──┘└──────────────┘┴┴└┘
doc └──┘ ┴ └┘
txt └──┘ ┴ └┘
par └──┘ ┴ └┘
pid └┘ ┴ ┴┴
st ─────────────────────────┘┴┴└─
1904 end
st ──┘
1905
1906 @[simp] theorem count_sub (a : α) (s t : multiset α) : count a (s - t) = count a s - count a t :=
id ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
src └──────┘ └───┘ ┴ ┴ └───┘ ┴ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
doc └──┘ └──────┘ └───┘ └───┘ └───┘
1907 begin
st └─────
1908 revert s, refine multiset.induction_on t (by simp) (λ b t IH s, _),
id └───────────────────┘ ┴
src └──────┘ └─────┘└───────────────────┘┴ ┴ ┴└──┘└┘ └───────────┘
typ └──────┘ └─────┘└───────────────────┘┴┴┴ ┴└──┘└┘ └───────────┘
doc └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
txt └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
par └──────┘ └─────┘ ┴ ┴ ┴└──┘└┘ └───────────┘
pid └┘ ┴ ┴ ┴ └─────┘ └───────────┘
st ─────────┘└──────────────────────────────────┘└───┘└───────────────┘└─
1909 rw [sub_cons, IH],
id └──────┘ └┘
src └──┘└──────┘└┘ ┴
typ └──┘└──────┘└┘└┘┴
doc └──┘ └┘ ┴
txt └──┘ └┘ ┴
par └──┘ └┘ ┴
pid └┘ └┘ ┴
st ─────────────┘└──┘└──
1910 by_cases ab : a = b,
id ┴ ┴ ┴
src └───────┘ └─┘ ┴┴┴
typ └───────┘ └─┘┴┴┴┴┴
doc └───────┘ └─┘ ┴ ┴
txt └───────┘ └─┘ ┴ ┴
par └───────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴
st ────────────────────┘└─
1911 { subst b, rw [count_erase_self, count_cons_self, sub_succ, pred_sub] },
id ┴ └──────────────┘ └─────────────┘ └──────┘ └──────┘
src └────┘ └──┘└──────────────┘└┘└─────────────┘└┘└──────┘└┘└──────┘└┘
typ └────┘┴ └──┘└──────────────┘└┘└─────────────┘└┘└──────┘└┘└──────┘└┘
doc └────┘ └──┘ └┘ └┘ └┘ └┘
txt └────┘ └──┘ └┘ └┘ └┘ └┘
par └────┘ └──┘ └┘ └┘ └┘ └┘
pid ┴ └┘ └┘ └┘ └┘ ┴┴
st ───┘└─────┘└────────────────────┘└───────────────┘└────────┘└────────┘┴┴└┘└
1912 { rw [count_erase_of_ne ab, count_cons_of_ne ab] }
id └───────────────┘ └┘ └──────────────┘ └┘
src └──┘└───────────────┘┴ └┘└──────────────┘┴ └┘
typ └──┘└───────────────┘┴└┘└┘└──────────────┘┴└┘└┘
doc └──┘ ┴ └┘ ┴ └┘
txt └──┘ ┴ └┘ ┴ └┘
par └──┘ ┴ └┘ ┴ └┘
pid └┘ ┴ └┘ ┴ ┴┴
st ───────────────────────────┘└───────────────────┘┴┴└─
1913 end
st ──┘
1914
1915 @[simp] theorem count_union (a : α) (s t : multiset α) : count a (s ∪ t) = max (count a s) (count a t) :=
id ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘ └───┘ ┴ ┴ └───┘ ┴ ┴
src └──────┘ └───┘ ┴ ┴ └─┘ └───┘ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘ └───┘ ┴ ┴ └───┘ ┴ ┴
doc └──┘ └──────┘ └───┘ └───┘ └───┘
1916 by simp [(∪), union, sub_add_eq_max, -add_comm]
id └───┘ └────────────┘
src └────┘ └──┘└───┘└┘└────────────┘└────────────
typ └────┘ └──┘└───┘└┘└────────────┘└────────────
doc └────┘ └──┘└───┘└┘ └────────────
txt └────┘ └──┘ └┘ └────────────
par └────┘ └──┘ └┘ └────────────
pid ┴┴ └──┘ └┘ └──────────┘└
st └─────────────────────────────────────────────
1917
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1918 @[simp] theorem count_inter (a : α) (s t : multiset α) : count a (s ∩ t) = min (count a s) (count a t) :=
id ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘ └───┘ ┴ ┴ └───┘ ┴ ┴
src └──────┘ └───┘ ┴ ┴ └─┘ └───┘ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ └─┘ └───┘ ┴ ┴ └───┘ ┴ ┴
doc └──┘ └──────┘ └───┘ └───┘ └───┘
1919 begin
st └─────
1920 apply @nat.add_left_cancel (count a (s - t)),
id └─────────────────┘ └───┘ ┴ ┴ ┴ ┴
src └────┘ └─────────────────┘┴ └───┘┴ ┴ ┴┴┴ └┘
typ └────┘ └─────────────────┘┴ └───┘┴┴┴ ┴┴┴┴┴└┘
doc └────┘ ┴ └───┘┴ ┴ ┴ ┴ └┘
txt └────┘ ┴ ┴ ┴ ┴ ┴ └┘
par └────┘ ┴ ┴ ┴ ┴ ┴ └┘
pid ┴ ┴ ┴ ┴ ┴ ┴ └┘
st ─────────────────────────────────────────────┘└─
1921 rw [← count_add, sub_add_inter, count_sub, sub_add_min],
id └───────┘ └───────────┘ └───────┘ └─────────┘
src └────┘└───────┘└┘└───────────┘└┘└───────┘└┘└─────────┘┴
typ └────┘└───────┘└┘└───────────┘└┘└───────┘└┘└─────────┘┴
doc └────┘ └┘ └┘ └┘ ┴
txt └────┘ └┘ └┘ └┘ ┴
par └────┘ └┘ └┘ └┘ ┴
pid └──┘ └┘ └┘ └┘ ┴
st ────────────────┘└─────────────┘└─────────┘└───────────┘└──
1922 end
st ──┘
1923
1924 lemma count_bind {m : multiset β} {f : β → multiset α} {a : α} :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘
1925 count a (bind m f) = sum (m.map $ λb, count a $ f b) :=
id └───┘ ┴ └──┘ ┴ ┴ ┴ └─┘ ┴└──┘ ┴ └───┘ ┴ ┴ ┴
src └───┘ └──┘ ┴ └─┘ └──┘ └───┘
typ └───┘ ┴ └──┘ ┴ ┴ ┴ └─┘ ┴└──┘ ┴ └───┘ ┴ ┴ ┴
doc └───┘ └──┘ └──┘ └───┘
1926 multiset.induction_on m (by simp) (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘ └──┘
typ └───────────────────┘ ┴ └──┘ └──┘
doc └──┘ └──┘
txt └──┘ └──┘
par └──┘ └──┘
st └───┘ └───┘
1927
1928 theorem le_count_iff_repeat_le {a : α} {s : multiset α} {n : ℕ} : n ≤ count a s ↔ repeat a n ≤ s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴ └───┘ ┴ └────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴
doc └──────┘ └───┘ └────┘
1929 quot.induction_on s $ λ l, le_count_iff_repeat_sublist.trans repeat_le_coe.symm
id └───────────────┘ ┴ ┴ └─────────────────────────┘└────┘ └───────────┘└───┘
src └───────────────┘ └─────────────────────────┘└────┘ └───────────┘└───┘
typ └───────────────┘ ┴ ┴ └─────────────────────────┘└────┘ └───────────┘└───┘
1930
1931 @[simp] theorem count_filter {p} [decidable_pred p]
id └────────────┘ ┴
src └────────────┘
typ └────────────┘ ┴
doc └──┘
1932 {a} {s : multiset α} (h : p a) : count a (filter p s) = count a s :=
id └──────┘ ┴ ┴ ┴ └───┘ ┴ └────┘ ┴ ┴ ┴ └───┘ ┴ ┴
src └──────┘ └───┘ └────┘ ┴ └───┘
typ └──────┘ ┴ ┴ ┴ └───┘ ┴ └────┘ ┴ ┴ ┴ └───┘ ┴ ┴
doc └──────┘ └───┘ └────┘ └───┘
1933 quot.induction_on s $ λ l, count_filter h
id └───────────────┘ ┴ ┴ └──────────┘ ┴
src └───────────────┘ └──────────┘
typ └───────────────┘ ┴ ┴ └──────────┘ ┴
1934
1935 theorem ext {s t : multiset α} : s = t ↔ ∀ a, count a s = count a t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
src └──────┘ ┴ ┴ └───┘ ┴ └───┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
doc └──────┘ └───┘ └───┘
1936 quotient.induction_on₂ s t $ λ l₁ l₂, quotient.eq.trans perm_iff_count
id └────────────────────┘ ┴ ┴ └┘ └┘ └─────────┘└────┘ └────────────┘
src └────────────────────┘ └─────────┘└────┘ └────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └─────────┘└────┘ └────────────┘
1937
1938 @[ext]
doc └─┘
1939 theorem ext' {s t : multiset α} : (∀ a, count a s = count a t) → s = t :=
id └──────┘ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───┘ ┴ └───┘ ┴
typ └──────┘ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └───┘ └───┘
1940 ext.2
id └─┘┴
src └─┘┴
typ └─┘┴
1941
1942 @[simp] theorem coe_inter (s t : list α) : (s ∩ t : multiset α) = (s.bag_inter t : list α) :=
id └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴└────────┘ ┴ └──┘ ┴
src └──┘ ┴ └──────┘ ┴ └────────┘ └──┘
typ └──┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴└────────┘ ┴ └──┘ ┴
doc └──┘ └──────┘
1943 by ext; simp
src └─┘ └────
typ └─┘ └────
doc └─┘ └────
txt └─┘ └────
par └─┘ └────
pid └
st └──────────
1944
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
1945 theorem le_iff_count {s t : multiset α} : s ≤ t ↔ ∀ a, count a s ≤ count a t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
src └──────┘ ┴ ┴ └───┘ ┴ └───┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴
doc └──────┘ └───┘ └───┘
1946 ⟨λ h a, count_le_of_le a h, λ al,
id ┴ ┴ └────────────┘ ┴ ┴ └┘
src └────────────┘
typ ┴ ┴ └────────────┘ ┴ ┴ └┘
1947 by rw ← (ext.2 (λ a, by simp [max_eq_right (al a)]) : s ∪ t = t);
id └─┘ └──────────┘ └┘ ┴ ┴ ┴ ┴ ┴
src └───┘ └─┘└─┘ └──┘ ┴└────┘└──────────┘┴ ┴ └┘└──┘ ┴┴┴ ┴┴┴ ┴
typ └───┘ └─┘└─┘ └──┘ ┴└────┘└──────────┘┴ └┘┴┴└┘└──┘┴┴┴┴ ┴┴┴┴┴
doc └───┘ └─┘ └──┘ ┴└────┘ ┴ ┴ └┘└──┘ ┴ ┴ ┴ ┴ ┴
txt └───┘ └─┘ └──┘ ┴└────┘ ┴ ┴ └┘└──┘ ┴ ┴ ┴ ┴ ┴
par └───┘ └─┘ └──┘ ┴└────┘ ┴ ┴ └┘└──┘ ┴ ┴ ┴ ┴ ┴
pid └─┘ └─┘ └──┘ └─────┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴
st └───────────────────┘└─────────────────────────┘└───────────────
1948 apply le_union_left⟩
id └───────────┘
src └────┘└───────────┘
typ └────┘└───────────┘
doc └────┘
txt └────┘
par └────┘
pid ┴
st ──────────────────────┘
1949
1950 instance : distrib_lattice (multiset α) :=
id └─────────────┘ └──────┘ ┴
src └─────────────┘ └──────┘
typ └─────────────┘ └──────┘ ┴
doc └─────────────┘ └──────┘
1951 { le_sup_inf := λ s t u, le_of_eq $ eq.symm $
id ┴ ┴ ┴ └──────┘ └─────┘
src └──────┘ └─────┘
typ ┴ ┴ ┴ └──────┘ └─────┘
1952 ext.2 $ λ a, by simp only [max_min_distrib_left,
id └─┘┴ ┴ └──────────────────┘
src └─┘┴ └─────────┘└──────────────────┘└─
typ └─┘┴ ┴ └─────────┘└──────────────────┘└─
doc └─────────┘ └─
txt └─────────┘ └─
par └─────────┘ └─
pid ┴└──┘└┘ └─
st └─────────────────────────────────
1953 multiset.count_inter, multiset.sup_eq_union, multiset.count_union, multiset.inf_eq_inter],
id └──────────────────┘ └───────────────────┘ └──────────────────┘ └───────────────────┘
src ─────┘└──────────────────┘└┘└───────────────────┘└┘└──────────────────┘└┘└───────────────────┘┴
typ ─────┘└──────────────────┘└┘└───────────────────┘└┘└──────────────────┘└┘└───────────────────┘┴
doc ─────┘ └┘ └┘ └┘ ┴
txt ─────┘ └┘ └┘ └┘ ┴
par ─────┘ └┘ └┘ └┘ ┴
pid ─────┘ └┘ └┘ └┘ ┴
st ──────────────────────────────────────────────────────────────────────────────────────────────┘
1954 ..multiset.lattice.lattice }
id └──────────────────────┘
src └──────────────────────┘
typ └──────────────────────┘
1955
1956 instance : semilattice_sup_bot (multiset α) :=
id └─────────────────┘ └──────┘ ┴
src └─────────────────┘ └──────┘
typ └─────────────────┘ └──────┘ ┴
doc └─────────────────┘ └──────┘
1957 { bot := 0,
1958 bot_le := zero_le,
id └─────┘
src └─────┘
typ └─────┘
1959 ..multiset.lattice.lattice }
id └──────────────────────┘
src └──────────────────────┘
typ └──────────────────────┘
1960
1961 end
1962
1963 /- relator -/
1964
1965 section rel
1966
1967 /-- `rel r s t` -- lift the relation `r` between two elements to a relation between `s` and `t`,
1968 s.t. there is a one-to-one mapping betweem elements in `s` and `t` following `r`. -/
1969 inductive rel (r : α → β → Prop) : multiset α → multiset β → Prop
id ┴ ┴ └──────┘ └──────┘
src └──────┘ └──────┘
typ ┴ ┴ └──────┘ └──────┘
doc └──────┘ └──────┘
1970 | zero {} : rel 0 0
1971 | cons {a b as bs} : r a b → rel as bs → rel (a :: as) (b :: bs)
id ┴ ┴ └┘ └┘ ┴ ┴ ┴ └─┘ └┘ └┘ ┴ └┘ └┘ ┴ └┘ └┘
src └┘ └┘
typ ┴ ┴ └┘ └┘ ┴ ┴ ┴ └─┘ └┘ └┘ ┴ └┘ └┘ ┴ └┘ └┘
doc └┘ └┘
1972
1973 run_cmd tactic.mk_iff_of_inductive_prop `multiset.rel `multiset.rel_iff
id └─────────────────────────────┘ ┴ ┴
src └─────────────────────────────┘ ┴ ┴
typ └─────────────────────────────┘ ┴ ┴
doc └─────────────────────────────┘
1974
1975 variables {δ : Type*} {r : α → β → Prop} {p : γ → δ → Prop}
1976
1977 private lemma rel_flip_aux {s t} (h : rel r s t) : rel (flip r) t s :=
id └─┘ ┴ ┴ ┴ └─┘ └──┘ ┴ ┴ ┴
src └─┘ └─┘ └──┘
typ └─┘ ┴ ┴ ┴ └─┘ └──┘ ┴ ┴ ┴
doc └─┘ └─┘
1978 rel.rec_on h rel.zero (assume _ _ _ _ h₀ h₁ ih, rel.cons h₀ ih)
id └────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ └┘ └┘ └──────┘ └┘ └┘
src └────────┘ └──────┘ └──────┘
typ └────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ └┘ └┘ └──────┘ └┘ └┘
1979
1980 lemma rel_flip {s t} : rel (flip r) s t ↔ rel r t s :=
id └─┘ └──┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
src └─┘ └──┘ ┴ └─┘
typ └─┘ └──┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
doc └─┘ └─┘
1981 ⟨rel_flip_aux, rel_flip_aux⟩
id └──────────┘ └──────────┘
src └──────────┘ └──────────┘
typ └──────────┘ └──────────┘
1982
1983 lemma rel_eq_refl {s : multiset α} : rel (=) s s :=
id └──────┘ ┴ └─┘ ┴ ┴ ┴
src └──────┘ └─┘ ┴
typ └──────┘ ┴ └─┘ ┴ ┴ ┴
doc └──────┘ └─┘
1984 multiset.induction_on s rel.zero (assume a s, rel.cons rfl)
id └───────────────────┘ ┴ └──────┘ ┴ ┴ └──────┘ └─┘
src └───────────────────┘ └──────┘ └──────┘ └─┘
typ └───────────────────┘ ┴ └──────┘ ┴ ┴ └──────┘ └─┘
1985
1986 lemma rel_eq {s t : multiset α} : rel (=) s t ↔ s = t :=
id └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─┘ ┴ ┴ ┴
typ └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └─┘
1987 begin
st └─────
1988 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ──────┘└─
1989 { assume h, induction h; simp * },
id ┴
src └──────┘ └────────┘ └─────┘
typ └──────┘ └────────┘┴ └─────┘
doc └──────┘ └────────┘ └─────┘
txt └──────┘ └────────┘ └─────┘
par └──────┘ └────────┘ └─────┘
pid └──────┘ ┴ ┴┴┴
st ───┘└──────┘└────────────────────┘└┘└
1990 { assume h, subst h, exact rel_eq_refl }
id ┴ └─────────┘
src └──────┘ └────┘ └────┘└─────────┘┴
typ └──────┘ └────┘┴ └────┘└─────────┘┴
doc └──────┘ └────┘ └────┘ ┴
txt └──────┘ └────┘ └────┘ ┴
par └──────┘ └────┘ └────┘ ┴
pid └──────┘ ┴ ┴ ┴
st ───────────┘└───────┘└──────────────────┘└─
1991 end
st ──┘
1992
1993 lemma rel.mono {p : α → β → Prop} {s t} (h : ∀a b, r a b → p a b) (hst : rel r s t) : rel p s t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
src └─┘ └─┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
doc └─┘ └─┘
1994 begin
st └─────
1995 induction hst,
id └─┘
src └────────┘
typ └────────┘└─┘
doc └────────┘
txt └────────┘
par └────────┘
pid ┴
st ──────────────┘└─
1996 case rel.zero { exact rel.zero },
id └──────┘
src └──────────────┘└────┘└──────┘┴┴
typ └──────────────┘└────┘└──────┘┴┴
doc └──────────────┘└────┘ ┴┴
txt └──────────────┘└────┘ ┴┴
par └──────────────┘└────┘ ┴┴
pid └───────┘┴└──────┘ └┘
st ────────────────┘└──────────────┘└┘└
1997 case rel.cons : a b s t hab hst ih { exact ih.cons (h a b hab) }
id └─────┘ ┴ ┴ ┴ └─┘
src └───────────────────────────────────┘└────┘└─────┘┴ ┴ ┴ ┴ └┘└┘
typ └───────────────────────────────────┘└────┘└─────┘┴ ┴┴┴┴┴┴└─┘└┘└┘
doc └───────────────────────────────────┘└────┘ ┴ ┴ ┴ ┴ └┘└┘
txt └───────────────────────────────────┘└────┘ ┴ ┴ ┴ ┴ └┘└┘
par └───────────────────────────────────┘└────┘ ┴ ┴ ┴ ┴ └┘└┘
pid └───────┘└───────────────────┘└───────┘ ┴ ┴ ┴ ┴ └─┘┴
st ─────────────────────────────────────┘└─────────────────────────┘┴┴
1998 end
st └─┘
1999
2000 lemma rel.add {s t u v} (hst : rel r s t) (huv : rel r u v) : rel r (s + u) (t + v) :=
id └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └─┘ └─┘ └─┘ ┴ ┴
typ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └─┘ └─┘
2001 begin
st └─────
2002 induction hst,
id └─┘
src └────────┘
typ └────────┘└─┘
doc └────────┘
txt └────────┘
par └────────┘
pid ┴
st ──────────────┘└─
2003 case rel.zero { simpa using huv },
id └─┘
src └──────────────┘└──────────┘ ┴┴
typ └──────────────┘└──────────┘└─┘┴┴
doc └──────────────┘└──────────┘ ┴┴
txt └──────────────┘└──────────┘ ┴┴
par └──────────────┘└──────────┘ ┴┴
pid └───────┘┴└────────────┘ └┘
st ────────────────┘└───────────────┘└┘└
2004 case rel.cons : a b s t hab hst ih { simpa using ih.cons hab }
id └─────┘ └─┘
src └───────────────────────────────────┘└──────────┘└─────┘┴ ┴└┘
typ └───────────────────────────────────┘└──────────┘└─────┘┴└─┘┴└┘
doc └───────────────────────────────────┘└──────────┘ ┴ ┴└┘
txt └───────────────────────────────────┘└──────────┘ ┴ ┴└┘
par └───────────────────────────────────┘└──────────┘ ┴ ┴└┘
pid └───────┘└───────────────────┘└─────────────┘ ┴ └┘┴
st ─────────────────────────────────────┘└───────────────────────┘┴┴
2005 end
st └─┘
2006
2007 lemma rel_flip_eq {s t : multiset α} : rel (λa b, b = a) s t ↔ s = t :=
id └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─┘ ┴ ┴ ┴
typ └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └─┘
2008 show rel (flip (=)) s t ↔ s = t, by rw [rel_flip, rel_eq, eq_comm]
id └─┘ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ └────┘ └─────┘
src └─┘ └──┘ ┴ ┴ ┴ └──┘└──────┘└┘└────┘└┘└─────┘└─
typ └─┘ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘└──────┘└┘└────┘└┘└─────┘└─
doc └─┘ └──┘ └┘ └┘ └─
txt └──┘ └┘ └┘ └─
par └──┘ └┘ └┘ └─
pid └┘ └┘ └┘ ┴└
st └───────────┘└──────┘└───────┘┴└
2009
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2010 @[simp] lemma rel_zero_left {b : multiset β} : rel r 0 b ↔ b = 0 :=
id └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─┘ ┴ ┴
typ └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └─┘
2011 by rw [rel_iff]; simp
id └─────┘
src └──┘└─────┘┴ └────
typ └──┘└─────┘┴ └────
doc └──┘ ┴ └────
txt └──┘ ┴ └────
par └──┘ ┴ └────
pid └┘ ┴ └
st └──────────┘┴└──────
2012
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2013 @[simp] lemma rel_zero_right {a : multiset α} : rel r a 0 ↔ a = 0 :=
id └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─┘ ┴ ┴
typ └──────┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └─┘
2014 by rw [rel_iff]; simp
id └─────┘
src └──┘└─────┘┴ └────
typ └──┘└─────┘┴ └────
doc └──┘ ┴ └────
txt └──┘ ┴ └────
par └──┘ ┴ └────
pid └┘ ┴ └
st └──────────┘┴└──────
2015
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2016 lemma rel_cons_left {a as bs} :
2017 rel r (a :: as) bs ↔ (∃b bs', r a b ∧ rel r as bs' ∧ bs = b :: bs') :=
id └─┘ ┴ ┴ └┘ └┘ └┘ ┴ ┴┴ └─┘┴ ┴ ┴ ┴ ┴ └─┘ ┴ └┘ └─┘ ┴ └┘ ┴ ┴ └┘ └─┘
src └─┘ └┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └┘
typ └─┘ ┴ ┴ └┘ └┘ └┘ ┴ ┴┴ └─┘┴ ┴ ┴ ┴ ┴ └─┘ ┴ └┘ └─┘ ┴ └┘ ┴ ┴ └┘ └─┘
doc └─┘ └┘ └─┘ └┘
2018 begin
st └─────
2019 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ──────┘└─
2020 { generalize hm : a :: as = m,
id ┴ └┘ └┘
src └──────────────┘ ┴└┘┴ ┴ ┴
typ └──────────────┘┴┴└┘┴└┘┴ ┴
doc └──────────────┘ ┴└┘┴ ┴ ┴
txt └──────────────┘ ┴ ┴ ┴ ┴
par └──────────────┘ ┴ ┴ ┴ ┴
pid └─┘└┘┴ ┴ ┴ ┴ ┴
st ───┘└─────────────────────────┘└─
2021 assume h,
src └──────┘
typ └──────┘
doc └──────┘
txt └──────┘
par └──────┘
pid └──────┘
st ───────────┘└─
2022 induction h generalizing as,
id ┴
src └────────┘ └──────────────┘
typ └────────┘┴└──────────────┘
doc └────────┘ └──────────────┘
txt └────────┘ └──────────────┘
par └────────┘ └──────────────┘
pid ┴ ┴└─────────────┘
st ──────────────────────────────┘└─
2023 case rel.zero { simp at hm, contradiction },
src └──────────────┘└────────┘└┘└────────────┘┴
typ └──────────────┘└────────┘└┘└────────────┘┴
doc └──────────────┘└────────┘└┘└────────────┘┴
txt └──────────────┘└────────┘└┘└────────────┘┴
par └──────────────┘└────────┘└┘└────────────┘┴
pid └───────┘┴└───────────────────────────┘
st ──────────────────┘└─────────┘└──────────────┘└┘└
2024 case rel.cons : a' b as' bs ha'b h ih {
src └───────────────────────────────────────
typ └───────────────────────────────────────
doc └───────────────────────────────────────
txt └───────────────────────────────────────
par └───────────────────────────────────────
pid └───────┘└──────────────────────┘└──
st ──────────────────────────────────────────┘└
2025 rcases cons_eq_cons.1 hm with ⟨eq₁, eq₂⟩ | ⟨h, cs, eq₁, eq₂⟩,
id └──────────┘ └┘
src ─────┘└─────┘└──────────┘└─┘ └──────────────────────────────────┘└─
typ ─────┘└─────┘└──────────┘└─┘└┘└──────────────────────────────────┘└─
doc ─────┘└─────┘ └─┘ └──────────────────────────────────┘└─
txt ─────┘└─────┘ └─┘ └──────────────────────────────────┘└─
par ─────┘└─────┘ └─┘ └──────────────────────────────────┘└─
pid ────────────┘ └─┘ └─────────────────────────────────────
st ─────────────────────────────────────────────────────────────────┘└─
2026 { subst eq₁, subst eq₂, exact ⟨b, bs, ha'b, h, rfl⟩ },
id └─┘ └─┘ ┴ └┘ └──┘ ┴ └─┘
src ───────┘└────┘ └┘└────┘ └┘└────┘ └┘ └┘ └┘ └┘└─┘└┘└──
typ ───────┘└────┘└─┘└┘└────┘└─┘└┘└────┘ ┴└┘└┘└┘└──┘└┘┴└┘└─┘└┘└──
doc ───────┘└────┘ └┘└────┘ └┘└────┘ └┘ └┘ └┘ └┘ └┘└──
txt ───────┘└────┘ └┘└────┘ └┘└────┘ └┘ └┘ └┘ └┘ └┘└──
par ───────┘└────┘ └┘└────┘ └┘└────┘ └┘ └┘ └┘ └┘ └┘└──
pid ─────────────┘ └──────┘ └──────┘ └┘ └┘ └┘ └┘ └────
st ──────┘└────────┘└─────────┘└────────────────────────────┘┴└─
2027 { rcases ih eq₂.symm with ⟨b', bs', h₁, h₂, eq⟩,
id └┘ └──────┘
src ───────┘└─────┘ ┴└──────┘└─────────────────────────┘└─
typ ───────┘└─────┘└┘┴└──────┘└─────────────────────────┘└─
doc ───────┘└─────┘ ┴ └─────────────────────────┘└─
txt ───────┘└─────┘ ┴ └─────────────────────────┘└─
par ───────┘└─────┘ ┴ └─────────────────────────┘└─
pid ──────────────┘ ┴ └────────────────────────────
st ────────────────────────────────────────────────────┘└─
2028 exact ⟨b', b::bs', h₁, eq₁.symm ▸ rel.cons ha'b h₂, eq.symm ▸ cons_swap _ _ _⟩ }
id └┘ ┴ └─┘ └┘ └──────┘ ┴ └──────┘ └──┘ └┘ └─────┘ └───────┘
src ───────┘└────┘ └┘ └┘ └┘└──────┘┴┴┴└──────┘┴ ┴ └┘└─────┘┴ ┴└───────┘└───────┘└─
typ ───────┘└────┘ └┘└┘┴ └─┘└┘└┘└┘└──────┘┴┴┴└──────┘┴└──┘┴└┘└┘└─────┘┴ ┴└───────┘└───────┘└─
doc ───────┘└────┘ └┘ └┘ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └───────┘└─
txt ───────┘└────┘ └┘ └┘ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └───────┘└─
par ───────┘└────┘ └┘ └┘ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └───────┘└─
pid ─────────────┘ └┘ └┘ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └──────────
st ───────────────────────────────────────────────────────────────────────────────────────┘└─
2029 } },
src ─────┘
typ ─────┘
doc ─────┘
txt ─────┘
par ─────┘
pid ────┘┴
st ────┘┴└┘└
2030 { exact assume ⟨b, bs', hab, h, eq⟩, eq.symm ▸ rel.cons hab h }
id └─┘ ┴ └┘ └───┘ └──────┘
src └────┘ └┘ └┘ └┘ └┘ └┘└┘└─┘ └───┘┴ ┴└──────┘┴ ┴ ┴
typ └────┘ └┘ └┘ └┘└─┘└┘┴└┘└┘└─┘ └───┘┴ ┴└──────┘┴ ┴ ┴
doc └────┘ └┘ └┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴ ┴ ┴
txt └────┘ └┘ └┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴ ┴ ┴
par └────┘ └┘ └┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴ ┴ ┴
pid ┴ └┘ └┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴ ┴ ┴
st ───────────────────────────────────────────────────────────────┘└─
2031 end
st ──┘
2032
2033 lemma rel_cons_right {as b bs} :
2034 rel r as (b :: bs) ↔ (∃a as', r a b ∧ rel r as' bs ∧ as = a :: as') :=
id └─┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴┴ └─┘┴ ┴ ┴ ┴ ┴ └─┘ ┴ └─┘ └┘ ┴ └┘ ┴ ┴ └┘ └─┘
src └─┘ └┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └┘
typ └─┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴┴ └─┘┴ ┴ ┴ ┴ ┴ └─┘ ┴ └─┘ └┘ ┴ └┘ ┴ ┴ └┘ └─┘
doc └─┘ └┘ └─┘ └┘
2035 begin
st └─────
2036 rw [← rel_flip, rel_cons_left],
id └──────┘ └───────────┘
src └────┘└──────┘└┘└───────────┘┴
typ └────┘└──────┘└┘└───────────┘┴
doc └────┘ └┘ ┴
txt └────┘ └┘ ┴
par └────┘ └┘ ┴
pid └──┘ └┘ ┴
st ───────────────┘└─────────────┘└──
2037 apply exists_congr, assume a,
id └──────────┘
src └────┘└──────────┘ └──────┘
typ └────┘└──────────┘ └──────┘
doc └────┘ └──────┘
txt └────┘ └──────┘
par └────┘ └──────┘
pid ┴ └──────┘
st ───────────────────┘└────────┘└─
2038 apply exists_congr, assume as',
id └──────────┘
src └────┘└──────────┘ └────────┘
typ └────┘└──────────┘ └────────┘
doc └────┘ └────────┘
txt └────┘ └────────┘
par └────┘ └────────┘
pid ┴ └────────┘
st ───────────────────┘└──────────┘└─
2039 rw [rel_flip, flip]
id └──────┘ └──┘
src └──┘└──────┘└┘└──┘└┘
typ └──┘└──────┘└┘└──┘└┘
doc └──┘ └┘ └┘
txt └──┘ └┘ └┘
par └──┘ └┘ └┘
pid └┘ └┘ ┴┴
st ─────────────┘└────┘┴┴
2040 end
st └─┘
2041
2042 lemma rel_add_left {as₀ as₁} :
2043 ∀{bs}, rel r (as₀ + as₁) bs ↔ (∃bs₀ bs₁, rel r as₀ bs₀ ∧ rel r as₁ bs₁ ∧ bs = bs₀ + bs₁) :=
id └┘ └─┘ ┴ └─┘ ┴ └─┘ └┘ ┴ ┴└─┘ └─┘┴ └─┘ ┴ └─┘ └─┘ ┴ └─┘ ┴ └─┘ └─┘ ┴ └┘ ┴ └─┘ ┴ └─┘
src └─┘ ┴ ┴ ┴ ┴ └─┘ ┴ └─┘ ┴ ┴ ┴
typ └┘ └─┘ ┴ └─┘ ┴ └─┘ └┘ ┴ ┴└─┘ └─┘┴ └─┘ ┴ └─┘ └─┘ ┴ └─┘ ┴ └─┘ └─┘ ┴ └┘ ┴ └─┘ ┴ └─┘
doc └─┘ └─┘ └─┘
2044 multiset.induction_on as₀ (by simp)
id └───────────────────┘ └─┘
src └───────────────────┘ └──┘
typ └───────────────────┘ └─┘ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
2045 begin
st └─────
2046 assume a s ih bs,
src └──────────────┘
typ └──────────────┘
doc └──────────────┘
txt └──────────────┘
par └──────────────┘
pid └──────────────┘
st ───────────────────┘└─
2047 simp only [ih, cons_add, rel_cons_left],
id └──────┘ └───────────┘
src └─────────┘ └┘└──────┘└┘└───────────┘┴
typ └─────────┘└┘└┘└──────┘└┘└───────────┘┴
doc └─────────┘ └┘ └┘ ┴
txt └─────────┘ └┘ └┘ ┴
par └─────────┘ └┘ └┘ ┴
pid ┴└──┘└┘ └┘ └┘ ┴
st ──────────────────────────────────────────┘└─
2048 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ────────┘└─
2049 { assume h,
src └──────┘
typ └──────┘
doc └──────┘
txt └──────┘
par └──────┘
pid └──────┘
st ─────┘└──────┘└─
2050 rcases h with ⟨b, bs', hab, h, rfl⟩,
id ┴
src └─────┘ └─────────────────────────┘
typ └─────┘┴└─────────────────────────┘
doc └─────┘ └─────────────────────────┘
txt └─────┘ └─────────────────────────┘
par └─────┘ └─────────────────────────┘
pid ┴ └─────────────────────────┘
st ────────────────────────────────────────┘└─
2051 rcases h with ⟨bs₀, bs₁, h₀, h₁, rfl⟩,
id ┴
src └─────┘ └───────────────────────────┘
typ └─────┘┴└───────────────────────────┘
doc └─────┘ └───────────────────────────┘
txt └─────┘ └───────────────────────────┘
par └─────┘ └───────────────────────────┘
pid ┴ └───────────────────────────┘
st ──────────────────────────────────────────┘└─
2052 exact ⟨b :: bs₀, bs₁, ⟨b, bs₀, hab, h₀, rfl⟩, h₁, by simp⟩ },
id └┘ └─┘ ┴ └─┘ └─┘ └┘ └─┘ └┘
src └────┘ ┴└┘┴ └┘ └┘ └┘ └┘ └┘ └┘└─┘└─┘ └┘ ┴└──┘└┘
typ └────┘ ┴└┘┴ └┘└─┘└┘ ┴└┘└─┘└┘└─┘└┘└┘└┘└─┘└─┘└┘└┘ ┴└──┘└┘
doc └────┘ ┴└┘┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ └┘ ┴└──┘└┘
txt └────┘ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ └┘ ┴└──┘└┘
par └────┘ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ └┘ ┴└──┘└┘
pid ┴ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ └┘ └────┘┴
st ─────────────────────────────────────────────────────────┘└───┘└┘└┘└
2053 { assume h,
src └──────┘
typ └──────┘
doc └──────┘
txt └──────┘
par └──────┘
pid └──────┘
st ─────────────┘└─
2054 rcases h with ⟨bs₀, bs₁, h, h₁, rfl⟩,
id ┴
src └─────┘ └──────────────────────────┘
typ └─────┘┴└──────────────────────────┘
doc └─────┘ └──────────────────────────┘
txt └─────┘ └──────────────────────────┘
par └─────┘ └──────────────────────────┘
pid ┴ └──────────────────────────┘
st ─────────────────────────────────────────┘└─
2055 rcases h with ⟨b, bs, hab, h₀, rfl⟩,
id ┴
src └─────┘ └─────────────────────────┘
typ └─────┘┴└─────────────────────────┘
doc └─────┘ └─────────────────────────┘
txt └─────┘ └─────────────────────────┘
par └─────┘ └─────────────────────────┘
pid ┴ └─────────────────────────┘
st ────────────────────────────────────────┘└─
2056 exact ⟨b, bs + bs₁, hab, ⟨bs, bs₁, h₀, h₁, rfl⟩, by simp⟩ }
id ┴ ┴ └─┘ └┘ └─┘ └┘ └┘ └─┘
src └────┘ └┘ ┴┴┴ └┘ └┘ └┘ └┘ └┘ └┘└─┘└─┘ ┴└──┘└┘
typ └────┘ ┴└┘ ┴┴┴ └┘└─┘└┘ └┘└┘└─┘└┘└┘└┘└┘└┘└─┘└─┘ ┴└──┘└┘
doc └────┘ └┘ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ ┴└──┘└┘
txt └────┘ └┘ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ ┴└──┘└┘
par └────┘ └┘ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ ┴└──┘└┘
pid ┴ └┘ ┴ ┴ └┘ └┘ └┘ └┘ └┘ └┘ └─┘ └────┘┴
st ────────────────────────────────────────────────────────┘└───┘└┘└─
2057 end
st ────┘
2058
2059 lemma rel_add_right {as bs₀ bs₁} :
2060 rel r as (bs₀ + bs₁) ↔ (∃as₀ as₁, rel r as₀ bs₀ ∧ rel r as₁ bs₁ ∧ as = as₀ + as₁) :=
id └─┘ ┴ └┘ └─┘ ┴ └─┘ ┴ ┴└─┘ └─┘┴ └─┘ ┴ └─┘ └─┘ ┴ └─┘ ┴ └─┘ └─┘ ┴ └┘ ┴ └─┘ ┴ └─┘
src └─┘ ┴ ┴ ┴ ┴ └─┘ ┴ └─┘ ┴ ┴ ┴
typ └─┘ ┴ └┘ └─┘ ┴ └─┘ ┴ ┴└─┘ └─┘┴ └─┘ ┴ └─┘ └─┘ ┴ └─┘ ┴ └─┘ └─┘ ┴ └┘ ┴ └─┘ ┴ └─┘
doc └─┘ └─┘ └─┘
2061 by rw [← rel_flip, rel_add_left]; simp [rel_flip]
id └──────┘ └──────────┘ └──────┘
src └────┘└──────┘└┘└──────────┘┴ └────┘└──────┘└─
typ └────┘└──────┘└┘└──────────┘┴ └────┘└──────┘└─
doc └────┘ └┘ ┴ └────┘ └─
txt └────┘ └┘ ┴ └────┘ └─
par └────┘ └┘ ┴ └────┘ └─
pid └──┘ └┘ ┴ ┴┴ ┴└
st └─────────────┘└────────────┘┴└─────────────────
2062
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2063 lemma rel_map_left {s : multiset γ} {f : γ → α} :
id └──────┘ ┴ ┴ ┴
src └──────┘
typ └──────┘ ┴ ┴ ┴
doc └──────┘
2064 ∀{t}, rel r (s.map f) t ↔ rel (λa b, r (f a) b) s t :=
id ┴ └─┘ ┴ ┴└──┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └─┘ └──┘ ┴ └─┘
typ ┴ └─┘ ┴ ┴└──┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └──┘ └─┘
2065 multiset.induction_on s (by simp) (by simp [rel_cons_left] {contextual := tt})
id └───────────────────┘ ┴ └───────────┘ └┘
src └───────────────────┘ └──┘ └────┘└───────────┘└┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └────┘└───────────┘└┘ └────────────┘└┘┴
doc └──┘ └────┘ └┘ └────────────┘ ┴
txt └──┘ └────┘ └┘ └────────────┘ ┴
par └──┘ └────┘ └┘ └────────────┘ ┴
pid ┴┴ ┴┴ └────────────┘ ┴
st └───┘ └──────────────────────────────────────┘
2066
2067 lemma rel_map_right {s : multiset α} {t : multiset γ} {f : γ → β} :
id └──────┘ ┴ └──────┘ ┴ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘ └──────┘
2068 rel r s (t.map f) ↔ rel (λa b, r a (f b)) s t :=
id └─┘ ┴ ┴ ┴└──┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └─┘ └──┘ ┴ └─┘
typ └─┘ ┴ ┴ ┴└──┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └──┘ └─┘
2069 by rw [← rel_flip, rel_map_left, ← rel_flip]; refl
id └──────┘ └──────────┘ └──────┘
src └────┘└──────┘└┘└──────────┘└──┘└──────┘┴ └────
typ └────┘└──────┘└┘└──────────┘└──┘└──────┘┴ └────
doc └────┘ └┘ └──┘ ┴ └────
txt └────┘ └┘ └──┘ ┴ └────
par └────┘ └┘ └──┘ ┴ └────
pid └──┘ └┘ └──┘ ┴ └
st └─────────────┘└────────────┘└──────────┘┴└──────
2070
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2071 lemma rel_join {s t} (h : rel (rel r) s t) : rel r s.join t.join :=
id └─┘ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴└───┘ ┴└───┘
src └─┘ └─┘ └─┘ └───┘ └───┘
typ └─┘ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴└───┘ ┴└───┘
doc └─┘ └─┘ └─┘ └───┘ └───┘
2072 begin
st └─────
2073 induction h,
id ┴
src └────────┘
typ └────────┘┴
doc └────────┘
txt └────────┘
par └────────┘
pid ┴
st ────────────┘└─
2074 case rel.zero { simp },
src └──────────────┘└───┘┴
typ └──────────────┘└───┘┴
doc └──────────────┘└───┘┴
txt └──────────────┘└───┘┴
par └──────────────┘└───┘┴
pid └───────┘┴└──────┘
st ────────────────┘└────┘└┘└
2075 case rel.cons : a b s t hab hst ih { simpa using hab.add ih }
id └─────┘ └┘
src └───────────────────────────────────┘└──────────┘└─────┘┴ ┴└┘
typ └───────────────────────────────────┘└──────────┘└─────┘┴└┘┴└┘
doc └───────────────────────────────────┘└──────────┘ ┴ ┴└┘
txt └───────────────────────────────────┘└──────────┘ ┴ ┴└┘
par └───────────────────────────────────┘└──────────┘ ┴ ┴└┘
pid └───────┘└───────────────────┘└─────────────┘ ┴ └┘┴
st ─────────────────────────────────────┘└──────────────────────┘┴┴
2076 end
st └─┘
2077
2078 lemma rel_map {p : γ → δ → Prop} {s t} {f : α → γ} {g : β → δ} (h : (r ⇒ p) f g) (hst : rel r s t) :
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
src ┴ └─┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
doc └─┘
2079 rel p (s.map f) (t.map g) :=
id └─┘ ┴ ┴└──┘ ┴ ┴└──┘ ┴
src └─┘ └──┘ └──┘
typ └─┘ ┴ ┴└──┘ ┴ ┴└──┘ ┴
doc └─┘ └──┘ └──┘
2080 by rw [rel_map_left, rel_map_right]; exact hst.mono h
id └──────────┘ └───────────┘ └──────┘ ┴
src └──┘└──────────┘└┘└───────────┘┴ └────┘└──────┘┴ └
typ └──┘└──────────┘└┘└───────────┘┴ └────┘└──────┘┴┴└
doc └──┘ └┘ ┴ └────┘ ┴ └
txt └──┘ └┘ ┴ └────┘ ┴ └
par └──┘ └┘ ┴ └────┘ ┴ └
pid └┘ └┘ ┴ ┴ ┴ └
st └───────────────┘└─────────────┘┴└──────────────────
2081
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2082 lemma rel_bind {p : γ → δ → Prop} {s t} {f : α → multiset γ} {g : β → multiset δ}
id ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴
doc └──────┘ └──────┘
2083 (h : (r ⇒ rel p) f g) (hst : rel r s t) :
id ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
src ┴ └─┘ └─┘
typ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
doc └─┘ └─┘
2084 rel p (s.bind f) (t.bind g) :=
id └─┘ ┴ ┴└───┘ ┴ ┴└───┘ ┴
src └─┘ └───┘ └───┘
typ └─┘ ┴ ┴└───┘ ┴ ┴└───┘ ┴
doc └─┘ └───┘ └───┘
2085 by apply rel_join; apply rel_map; assumption
id └──────┘ └─────┘
src └────┘└──────┘ └────┘└─────┘ └──────────
typ └────┘└──────┘ └────┘└─────┘ └──────────
doc └────┘ └────┘ └──────────
txt └────┘ └────┘ └──────────
par └────┘ └────┘ └──────────
pid ┴ ┴ └
st └──────────────────────────────────────────
2086
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2087 lemma card_eq_card_of_rel {r : α → β → Prop} {s : multiset α} {t : multiset β} (h : rel r s t) :
id ┴ ┴ └──────┘ ┴ └──────┘ ┴ └─┘ ┴ ┴ ┴
src └──────┘ └──────┘ └─┘
typ ┴ ┴ └──────┘ ┴ └──────┘ ┴ └─┘ ┴ ┴ ┴
doc └──────┘ └──────┘ └─┘
2088 card s = card t :=
id └──┘ ┴ ┴ └──┘ ┴
src └──┘ ┴ └──┘
typ └──┘ ┴ ┴ └──┘ ┴
doc └──┘ └──┘
2089 by induction h; simp [*]
id ┴
src └────────┘ └────────
typ └────────┘┴ └────────
doc └────────┘ └────────
txt └────────┘ └────────
par └────────┘ └────────
pid ┴ ┴└─┘└
st └──────────────────────
2090
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2091 lemma exists_mem_of_rel_of_mem {r : α → β → Prop} {s : multiset α} {t : multiset β} (h : rel r s t) :
id ┴ ┴ └──────┘ ┴ └──────┘ ┴ └─┘ ┴ ┴ ┴
src └──────┘ └──────┘ └─┘
typ ┴ ┴ └──────┘ ┴ └──────┘ ┴ └─┘ ┴ ┴ ┴
doc └──────┘ └──────┘ └─┘
2092 ∀ {a : α} (ha : a ∈ s), ∃ b ∈ t, r a b :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
src ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴
2093 begin
st └─────
2094 induction h with x y s t hxy hst ih,
id ┴
src └────────┘ └──────────────────────┘
typ └────────┘┴└──────────────────────┘
doc └────────┘ └──────────────────────┘
txt └────────┘ └──────────────────────┘
par └────────┘ └──────────────────────┘
pid ┴ ┴└─────────────────────┘
st ────────────────────────────────────┘└─
2095 { simp },
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
pid ┴
st ───┘└───┘└┘└
2096 { assume a ha,
src └─────────┘
typ └─────────┘
doc └─────────┘
txt └─────────┘
par └─────────┘
pid └─────────┘
st ──────────────┘└─
2097 cases mem_cons.1 ha with ha ha,
id └──────┘ └┘
src └────┘└──────┘└─┘ └─────────┘
typ └────┘└──────┘└─┘└┘└─────────┘
doc └────┘ └─┘ └─────────┘
txt └────┘ └─┘ └─────────┘
par └────┘ └─┘ └─────────┘
pid ┴ └─┘ └─────────┘
st ─────────────────────────────────┘└─
2098 { exact ⟨y, mem_cons_self _ _, ha.symm ▸ hxy⟩ },
id ┴ └───────────┘ └─────┘ ┴ └─┘
src └────┘ └┘└───────────┘└────┘└─────┘┴┴┴ └┘
typ └────┘ ┴└┘└───────────┘└────┘└─────┘┴┴┴└─┘└┘
doc └────┘ └┘ └────┘ ┴ ┴ └┘
txt └────┘ └┘ └────┘ ┴ ┴ └┘
par └────┘ └┘ └────┘ ┴ ┴ └┘
pid ┴ └┘ └────┘ ┴ ┴ ┴┴
st ─────┘└──────────────────────────────────────────┘└┘└
2099 { rcases ih ha with ⟨b, hbt, hab⟩,
id └┘ └┘
src └─────┘ ┴ └─────────────────┘
typ └─────┘└┘┴└┘└─────────────────┘
doc └─────┘ ┴ └─────────────────┘
txt └─────┘ ┴ └─────────────────┘
par └─────┘ ┴ └─────────────────┘
pid ┴ ┴ └─────────────────┘
st ────────────────────────────────────┘└─
2100 exact ⟨b, mem_cons.2 (or.inr hbt), hab⟩ } }
id ┴ └──────┘ └────┘ └─┘ └─┘
src └────┘ └┘└──────┘└─┘ └────┘┴ └─┘ └┘
typ └────┘ ┴└┘└──────┘└─┘ └────┘┴└─┘└─┘└─┘└┘
doc └────┘ └┘ └─┘ ┴ └─┘ └┘
txt └────┘ └┘ └─┘ ┴ └─┘ └┘
par └────┘ └┘ └─┘ ┴ └─┘ └┘
pid ┴ └┘ └─┘ ┴ └─┘ ┴┴
st ─────────────────────────────────────────────┘└───
2101 end
st ──┘
2102
2103 end rel
2104
2105 section map
2106
2107 theorem map_eq_map {f : α → β} (hf : function.injective f) {s t : multiset α} :
id ┴ ┴ └────────────────┘ ┴ └──────┘ ┴
src └────────────────┘ └──────┘
typ ┴ ┴ └────────────────┘ ┴ └──────┘ ┴
doc └──────┘
2108 s.map f = t.map f ↔ s = t :=
id ┴└──┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴
src └──┘ ┴ └──┘ ┴ ┴
typ ┴└──┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──┘
2109 by rw [← rel_eq, ← rel_eq, rel_map_left, rel_map_right]; simp [hf.eq_iff]
id └────┘ └────┘ └──────────┘ └───────────┘
src └────┘└────┘└──┘└────┘└┘└──────────┘└┘└───────────┘┴ └────┘ └─
typ └────┘└────┘└──┘└────┘└┘└──────────┘└┘└───────────┘┴ └────┘└───────┘└─
doc └────┘ └──┘ └┘ └┘ ┴ └────┘ └─
txt └────┘ └──┘ └┘ └┘ ┴ └────┘ └─
par └────┘ └──┘ └┘ └┘ ┴ └────┘ └─
pid └──┘ └──┘ └┘ └┘ ┴ ┴┴ ┴└
st └───────────┘└────────┘└────────────┘└─────────────┘┴└──────────────────
2110
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2111 theorem injective_map {f : α → β} (hf : function.injective f) :
id ┴ ┴ └────────────────┘ ┴
src └────────────────┘
typ ┴ ┴ └────────────────┘ ┴
2112 function.injective (multiset.map f) :=
id └────────────────┘ └──────────┘ ┴
src └────────────────┘ └──────────┘
typ └────────────────┘ └──────────┘ ┴
doc └──────────┘
2113 assume x y, (map_eq_map hf).1
id ┴ ┴ └────────┘ └┘ ┴
src └────────┘ ┴
typ ┴ ┴ └────────┘ └┘ ┴
2114
2115 end map
2116
2117 section quot
2118
2119 theorem map_mk_eq_map_mk_of_rel {r : α → α → Prop} {s t : multiset α} (hst : s.rel r t) :
id ┴ ┴ └──────┘ ┴ ┴└──┘ ┴ ┴
src └──────┘ └──┘
typ ┴ ┴ └──────┘ ┴ ┴└──┘ ┴ ┴
doc └──────┘ └──┘
2120 s.map (quot.mk r) = t.map (quot.mk r) :=
id ┴└──┘ └─────┘ ┴ ┴ ┴└──┘ └─────┘ ┴
src └──┘ ┴ └──┘
typ ┴└──┘ └─────┘ ┴ ┴ ┴└──┘ └─────┘ ┴
doc └──┘ └──┘
2121 rel.rec_on hst rfl $ assume a b s t hab hst ih, by simp [ih, quot.sound hab]
id └────────┘ └─┘ └─┘ ┴ ┴ ┴ ┴ └─┘ └─┘ └┘ └┘ └────────┘ └─┘
src └────────┘ └─┘ └────┘ └┘└────────┘┴ └─
typ └────────┘ └─┘ └─┘ ┴ ┴ ┴ ┴ └─┘ └─┘ └┘ └────┘└┘└┘└────────┘┴└─┘└─
doc └────┘ └┘ ┴ └─
txt └────┘ └┘ ┴ └─
par └────┘ └┘ ┴ └─
pid ┴┴ └┘ ┴ ┴└
st └──────────────────────────
2122
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2123 theorem exists_multiset_eq_map_quot_mk {r : α → α → Prop} (s : multiset (quot r)) :
id ┴ ┴ └──────┘ └──┘ ┴
src └──────┘
typ ┴ ┴ └──────┘ └──┘ ┴
doc └──────┘
2124 ∃t:multiset α, s = t.map (quot.mk r) :=
id ┴ └──────┘ ┴┴ ┴ ┴ ┴└──┘ └─────┘ ┴
src ┴ └──────┘ ┴ ┴ └──┘
typ ┴ └──────┘ ┴┴ ┴ ┴ ┴└──┘ └─────┘ ┴
doc └──────┘ └──┘
2125 multiset.induction_on s ⟨0, rfl⟩ $
id └───────────────────┘ ┴ └─┘
src └───────────────────┘ └─┘
typ └───────────────────┘ ┴ └─┘
2126 assume a s ⟨t, ht⟩, quot.induction_on a $ assume a, ht.symm ▸ ⟨a::t, (map_cons _ _ _).symm⟩
id ┴ ┴ ┴┴ └┘ └───────────────┘ ┴ ┴ └───┘ ┴ ┴└┘ └──────┘ └──┘
src └───────────────┘ └───┘ ┴ └┘ └──────┘ └──┘
typ ┴ ┴ ┴┴ └┘ └───────────────┘ ┴ ┴ └───┘ ┴ ┴└┘ └──────┘ └──┘
doc └┘
2127
2128 theorem induction_on_multiset_quot
2129 {r : α → α → Prop} {p : multiset (quot r) → Prop} (s : multiset (quot r)) :
id ┴ ┴ └──────┘ └──┘ ┴ └──────┘ └──┘ ┴
src └──────┘ └──────┘
typ ┴ ┴ └──────┘ └──┘ ┴ └──────┘ └──┘ ┴
doc └──────┘ └──────┘
2130 (∀s:multiset α, p (s.map (quot.mk r))) → p s :=
id ┴ └──────┘ ┴ ┴ ┴└──┘ └─────┘ ┴ ┴ ┴
src └──────┘ └──┘
typ ┴ └──────┘ ┴ ┴ ┴└──┘ └─────┘ ┴ ┴ ┴
doc └──────┘ └──┘
2131 match s, exists_multiset_eq_map_quot_mk s with _, ⟨t, rfl⟩ := assume h, h _ end
id ┴ └────────────────────────────┘ ┴ └─┘ ┴ ┴
src └────────────────────────────┘ └─┘
typ ┴ └────────────────────────────┘ ┴ └─┘ ┴ ┴
2132
2133 end quot
2134
2135 /- disjoint -/
2136
2137 /-- `disjoint s t` means that `s` and `t` have no elements in common. -/
2138 def disjoint (s t : multiset α) : Prop := ∀ ⦃a⦄, a ∈ s → a ∈ t → false
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘
src └──────┘ ┴ ┴ └───┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘
doc └──────┘
2139
2140 @[simp] theorem coe_disjoint (l₁ l₂ : list α) : @disjoint α l₁ l₂ ↔ l₁.disjoint l₂ := iff.rfl
id └──┘ ┴ └──────┘ ┴ └┘ └┘ ┴ └┘└───────┘ └┘ └─────┘
src └──┘ └──────┘ ┴ └───────┘ └─────┘
typ └──┘ ┴ └──────┘ ┴ └┘ └┘ ┴ └┘└───────┘ └┘ └─────┘
doc └──┘ └──────┘ └───────┘
2141
2142 theorem disjoint.symm {s t : multiset α} (d : disjoint s t) : disjoint t s
id └──────┘ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2143 | a i₂ i₁ := d i₁ i₂
id └┘ └┘ ┴
typ └┘ └┘ ┴
2144
2145 @[simp] theorem disjoint_comm {s t : multiset α} : disjoint s t ↔ disjoint t s :=
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘ ┴ └──────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘ └──────┘
2146 ⟨disjoint.symm, disjoint.symm⟩
id └───────────┘ └───────────┘
src └───────────┘ └───────────┘
typ └───────────┘ └───────────┘
2147
2148 theorem disjoint_left {s t : multiset α} : disjoint s t ↔ ∀ {a}, a ∈ s → a ∉ t := iff.rfl
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘
src └──────┘ └──────┘ ┴ ┴ ┴ └─────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘
doc └──────┘ └──────┘
2149
2150 theorem disjoint_right {s t : multiset α} : disjoint s t ↔ ∀ {a}, a ∈ t → a ∉ s :=
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ ┴ ┴ ┴
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘
2151 disjoint_comm
id └───────────┘
src └───────────┘
typ └───────────┘
2152
2153 theorem disjoint_iff_ne {s t : multiset α} : disjoint s t ↔ ∀ a ∈ s, ∀ b ∈ t, a ≠ b :=
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ ┴ ┴
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘
2154 by simp [disjoint_left, imp_not_comm]
id └───────────┘ └──────────┘
src └────┘└───────────┘└┘└──────────┘└─
typ └────┘└───────────┘└┘└──────────┘└─
doc └────┘ └┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └───────────────────────────────────
2155
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2156 theorem disjoint_of_subset_left {s t u : multiset α} (h : s ⊆ u) (d : disjoint u t) : disjoint s t
id └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ └──────┘ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2157 | x m₁ := d (h m₁)
id └┘ ┴ ┴
typ └┘ ┴ ┴
2158
2159 theorem disjoint_of_subset_right {s t u : multiset α} (h : t ⊆ u) (d : disjoint s u) : disjoint s t
id └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ └──────┘ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2160 | x m m₁ := d m (h m₁)
id ┴ └┘ ┴ ┴
typ ┴ └┘ ┴ ┴
2161
2162 theorem disjoint_of_le_left {s t u : multiset α} (h : s ≤ u) : disjoint u t → disjoint s t :=
id └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ └──────┘ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2163 disjoint_of_subset_left (subset_of_le h)
id └─────────────────────┘ └──────────┘ ┴
src └─────────────────────┘ └──────────┘
typ └─────────────────────┘ └──────────┘ ┴
2164
2165 theorem disjoint_of_le_right {s t u : multiset α} (h : t ≤ u) : disjoint s u → disjoint s t :=
id └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ └──────┘ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2166 disjoint_of_subset_right (subset_of_le h)
id └──────────────────────┘ └──────────┘ ┴
src └──────────────────────┘ └──────────┘
typ └──────────────────────┘ └──────────┘ ┴
2167
2168 @[simp] theorem zero_disjoint (l : multiset α) : disjoint 0 l
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
2169 | a := (not_mem_nil a).elim
id ┴ └─────────┘ └──┘
src └─────────┘ └──┘
typ ┴ └─────────┘ └──┘
2170
2171 @[simp] theorem singleton_disjoint {l : multiset α} {a : α} : disjoint (a::0) l ↔ a ∉ l :=
id └──────┘ ┴ ┴ └──────┘ ┴└┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ └┘ ┴ ┴
typ └──────┘ ┴ ┴ └──────┘ ┴└┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──────┘ └┘
2172 by simp [disjoint]; refl
id └──────┘
src └────┘└──────┘┴ └────
typ └────┘└──────┘┴ └────
doc └────┘└──────┘┴ └────
txt └────┘ ┴ └────
par └────┘ ┴ └────
pid ┴┴ ┴ └
st └──────────────────────
2173
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2174 @[simp] theorem disjoint_singleton {l : multiset α} {a : α} : disjoint l (a::0) ↔ a ∉ l :=
id └──────┘ ┴ ┴ └──────┘ ┴ ┴└┘ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ └┘ ┴ ┴
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴└┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──────┘ └┘
2175 by rw disjoint_comm; simp
id └───────────┘
src └─┘└───────────┘ └────
typ └─┘└───────────┘ └────
doc └─┘ └────
txt └─┘ └────
par └─┘ └────
pid ┴ └
st └───────────────────────
2176
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2177 @[simp] theorem disjoint_add_left {s t u : multiset α} :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
2178 disjoint (s + t) u ↔ disjoint s u ∧ disjoint t u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ ┴ └──────┘ ┴ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2179 by simp [disjoint, or_imp_distrib, forall_and_distrib]
id └──────┘ └────────────┘ └────────────────┘
src └────┘└──────┘└┘└────────────┘└┘└────────────────┘└─
typ └────┘└──────┘└┘└────────────┘└┘└────────────────┘└─
doc └────┘└──────┘└┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └────────────────────────────────────────────────────
2180
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2181 @[simp] theorem disjoint_add_right {s t u : multiset α} :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
2182 disjoint s (t + u) ↔ disjoint s t ∧ disjoint s u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ ┴ └──────┘ ┴ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2183 disjoint_comm.trans $ by simp [disjoint_append_left]
id └───────────┘└────┘ └──────────────────┘
src └───────────┘└────┘ └────┘└──────────────────┘└─
typ └───────────┘└────┘ └────┘└──────────────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └────────────────────────────
2184
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2185 @[simp] theorem disjoint_cons_left {a : α} {s t : multiset α} :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2186 disjoint (a::s) t ↔ a ∉ t ∧ disjoint s t :=
id └──────┘ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └┘ ┴ ┴ ┴ └──────┘
typ └──────┘ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └┘ └──────┘
2187 (@disjoint_add_left _ (a::0) s t).trans $ by simp
id └───────────────┘ ┴└┘ ┴ ┴ └───┘
src └───────────────┘ └┘ └───┘ └────
typ └───────────────┘ ┴└┘ ┴ ┴ └───┘ └────
doc └┘ └────
txt └────
par └────
pid └
st └─────
2188
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2189 @[simp] theorem disjoint_cons_right {a : α} {s t : multiset α} :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2190 disjoint s (a::t) ↔ a ∉ s ∧ disjoint s t :=
id └──────┘ ┴ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └┘ ┴ ┴ ┴ └──────┘
typ └──────┘ ┴ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └┘ └──────┘
2191 disjoint_comm.trans $ by simp [disjoint_cons_left]
id └───────────┘└────┘ └────────────────┘
src └───────────┘└────┘ └────┘└────────────────┘└─
typ └───────────┘└────┘ └────┘└────────────────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └──────────────────────────
2192
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2193 theorem inter_eq_zero_iff_disjoint [decidable_eq α] {s t : multiset α} : s ∩ t = 0 ↔ disjoint s t :=
id └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────────┘ └──────┘ ┴ ┴ ┴ └──────┘
typ └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘
2194 by rw ← subset_zero; simp [subset_iff, disjoint]
id └─────────┘ └────────┘ └──────┘
src └───┘└─────────┘ └────┘└────────┘└┘└──────┘└─
typ └───┘└─────────┘ └────┘└────────┘└┘└──────┘└─
doc └───┘ └────┘ └┘└──────┘└─
txt └───┘ └────┘ └┘ └─
par └───┘ └────┘ └┘ └─
pid └─┘ ┴┴ └┘ ┴└
st └──────────────────────────────────────────────
2195
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2196 @[simp] theorem disjoint_union_left [decidable_eq α] {s t u : multiset α} :
id └──────────┘ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
2197 disjoint (s ∪ t) u ↔ disjoint s u ∧ disjoint t u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ ┴ └──────┘ ┴ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2198 by simp [disjoint, or_imp_distrib, forall_and_distrib]
id └──────┘ └────────────┘ └────────────────┘
src └────┘└──────┘└┘└────────────┘└┘└────────────────┘└─
typ └────┘└──────┘└┘└────────────┘└┘└────────────────┘└─
doc └────┘└──────┘└┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └────────────────────────────────────────────────────
2199
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2200 @[simp] theorem disjoint_union_right [decidable_eq α] {s t u : multiset α} :
id └──────────┘ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘
2201 disjoint s (t ∪ u) ↔ disjoint s t ∧ disjoint s u :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ ┴ └──────┘ ┴ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2202 by simp [disjoint, or_imp_distrib, forall_and_distrib]
id └──────┘ └────────────┘ └────────────────┘
src └────┘└──────┘└┘└────────────┘└┘└────────────────┘└─
typ └────┘└──────┘└┘└────────────┘└┘└────────────────┘└─
doc └────┘└──────┘└┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └────────────────────────────────────────────────────
2203
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2204 lemma disjoint_map_map {f : α → γ} {g : β → γ} {s : multiset α} {t : multiset β} :
id ┴ ┴ ┴ ┴ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ ┴ ┴ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
2205 disjoint (s.map f) (t.map g) ↔ (∀a∈s, ∀b∈t, f a ≠ g b) :=
id └──────┘ ┴└──┘ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──┘ ┴└──┘ ┴ ┴
typ └──────┘ ┴└──┘ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──┘ └──┘
2206 begin
st └─────
2207 simp [disjoint],
id └──────┘
src └────┘└──────┘┴
typ └────┘└──────┘┴
doc └────┘└──────┘┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st ────────────────┘└─
2208 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ──────┘└─
2209 from assume h a ha b hb eq, h _ ha rfl _ hb eq.symm,
id └─┘ └───┘
src └───┘ └───────────────┘ └─┘ ┴└─┘└─┘ ┴ └───┘
typ └───┘ └───────────────┘ └─┘ ┴└─┘└─┘ ┴ └───┘
doc └───┘ └───────────────┘ └─┘ ┴ └─┘ ┴
txt └───┘ └───────────────┘ └─┘ ┴ └─┘ ┴
par └───┘ └───────────────┘ └─┘ ┴ └─┘ ┴
pid └───┘ └───────────────┘ └─┘ ┴ └─┘ ┴
st ────────────────────────────────────────────────────┘└─
2210 from assume h c a ha eq₁ b hb eq₂, h _ ha _ hb (eq₂.symm ▸ eq₁)
id ┴
src └───┘ └──────────────────────┘ └─┘ └─┘ ┴ ┴┴┴ └┘
typ └───┘ └──────────────────────┘ └─┘ └─┘ ┴ ┴┴┴ └┘
doc └───┘ └──────────────────────┘ └─┘ └─┘ ┴ ┴ ┴ └┘
txt └───┘ └──────────────────────┘ └─┘ └─┘ ┴ ┴ ┴ └┘
par └───┘ └──────────────────────┘ └─┘ └─┘ ┴ ┴ ┴ └┘
pid └───┘ └──────────────────────┘ └─┘ └─┘ ┴ ┴ ┴ ┴┴
st ─────────────────────────────────────────────────────────────────┘
2211 end
st └─┘
2212
2213 /-- `pairwise r m` states that there exists a list of the elements s.t. `r` holds pairwise on this list. -/
2214 def pairwise (r : α → α → Prop) (m : multiset α) : Prop :=
id ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ └──────┘ ┴
doc └──────┘
2215 ∃l:list α, m = l ∧ l.pairwise r
id ┴ └──┘ ┴┴ ┴ ┴ ┴ ┴ ┴└───────┘ ┴
src ┴ └──┘ ┴ ┴ ┴ └───────┘
typ ┴ └──┘ ┴┴ ┴ ┴ ┴ ┴ ┴└───────┘ ┴
doc └───────┘
2216
2217 lemma pairwise_coe_iff_pairwise {r : α → α → Prop} (hr : symmetric r) {l : list α} :
id ┴ ┴ └───────┘ ┴ └──┘ ┴
src └───────┘ └──┘
typ ┴ ┴ └───────┘ ┴ └──┘ ┴
2218 multiset.pairwise r l ↔ l.pairwise r :=
id └───────────────┘ ┴ ┴ ┴ ┴└───────┘ ┴
src └───────────────┘ ┴ └───────┘
typ └───────────────┘ ┴ ┴ ┴ ┴└───────┘ ┴
doc └───────────────┘ └───────┘
2219 iff.intro
id └───────┘
src └───────┘
typ └───────┘
2220 (assume ⟨l', eq, h⟩, (list.perm_pairwise hr (quotient.exact eq)).2 h)
id ┴ └┘ ┴ └────────────────┘ └┘ └────────────┘ ┴
src └┘ └────────────────┘ └────────────┘ ┴
typ ┴ └┘ ┴ └────────────────┘ └┘ └────────────┘ ┴
2221 (assume h, ⟨l, rfl, h⟩)
id ┴ ┴ └─┘ ┴
src └─┘
typ ┴ ┴ └─┘ ┴
2222
2223 /- nodup -/
2224
2225 /-- `nodup s` means that `s` has no duplicates, i.e. the multiplicity of
2226 any element is at most 1. -/
2227 def nodup (s : multiset α) : Prop :=
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
2228 quot.lift_on s nodup (λ s t p, propext $ perm_nodup p)
id └──────────┘ ┴ └───┘ ┴ ┴ ┴ └─────┘ └────────┘ ┴
src └──────────┘ └───┘ └─────┘ └────────┘
typ └──────────┘ ┴ └───┘ ┴ ┴ ┴ └─────┘ └────────┘ ┴
doc └───┘
2229
2230 @[simp] theorem coe_nodup {l : list α} : @nodup α l ↔ l.nodup := iff.rfl
id └──┘ ┴ └───┘ ┴ ┴ ┴ ┴└────┘ └─────┘
src └──┘ └───┘ ┴ └────┘ └─────┘
typ └──┘ ┴ └───┘ ┴ ┴ ┴ ┴└────┘ └─────┘
doc └──┘ └───┘ └────┘
2231
2232 @[simp] theorem forall_mem_ne {a : α} {l : list α} : (∀ (a' : α), a' ∈ l → ¬a = a') ↔ a ∉ l :=
id ┴ └──┘ ┴ ┴ └┘ ┴ ┴ ┴┴ ┴ └┘ ┴ ┴ ┴ ┴
src └──┘ ┴ ┴ ┴ ┴ ┴
typ ┴ └──┘ ┴ ┴ └┘ ┴ ┴ ┴┴ ┴ └┘ ┴ ┴ ┴ ┴
doc └──┘
2233 ⟨λ h m, h _ m rfl, λ h a' m e, h (e.symm ▸ m)⟩
id ┴ ┴ ┴ ┴ └─┘ ┴ └┘ ┴ ┴ ┴ ┴└───┘ ┴ ┴
src └─┘ └───┘ ┴
typ ┴ ┴ ┴ ┴ └─┘ ┴ └┘ ┴ ┴ ┴ ┴└───┘ ┴ ┴
2234
2235 @[simp] theorem nodup_zero : @nodup α 0 := pairwise.nil
id └───┘ ┴ └──────────┘
src └───┘ └──────────┘
typ └───┘ ┴ └──────────┘
doc └──┘ └───┘
2236
2237 @[simp] theorem nodup_cons {a : α} {s : multiset α} : nodup (a::s) ↔ a ∉ s ∧ nodup s :=
id ┴ └──────┘ ┴ └───┘ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴
src └──────┘ └───┘ └┘ ┴ ┴ ┴ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴└┘┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴
doc └──┘ └──────┘ └───┘ └┘ └───┘
2238 quot.induction_on s $ λ l, nodup_cons
id └───────────────┘ ┴ ┴ └────────┘
src └───────────────┘ └────────┘
typ └───────────────┘ ┴ ┴ └────────┘
2239
2240 theorem nodup_cons_of_nodup {a : α} {s : multiset α} (m : a ∉ s) (n : nodup s) : nodup (a::s) :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ └───┘ ┴└┘┴
src └──────┘ ┴ └───┘ └───┘ └┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ └───┘ ┴└┘┴
doc └──────┘ └───┘ └───┘ └┘
2241 nodup_cons.2 ⟨m, n⟩
id └────────┘┴ ┴ ┴
src └────────┘┴
typ └────────┘┴ ┴ ┴
2242
2243 theorem nodup_singleton : ∀ a : α, nodup (a::0) := nodup_singleton
id ┴ └───┘ ┴└┘ └─────────────┘
src └───┘ └┘ └─────────────┘
typ ┴ └───┘ ┴└┘ └─────────────┘
doc └───┘ └┘
2244
2245 theorem nodup_of_nodup_cons {a : α} {s : multiset α} (h : nodup (a::s)) : nodup s :=
id ┴ └──────┘ ┴ └───┘ ┴└┘┴ └───┘ ┴
src └──────┘ └───┘ └┘ └───┘
typ ┴ └──────┘ ┴ └───┘ ┴└┘┴ └───┘ ┴
doc └──────┘ └───┘ └┘ └───┘
2246 (nodup_cons.1 h).2
id └────────┘┴ ┴ ┴
src └────────┘┴ ┴
typ └────────┘┴ ┴ ┴
2247
2248 theorem not_mem_of_nodup_cons {a : α} {s : multiset α} (h : nodup (a::s)) : a ∉ s :=
id ┴ └──────┘ ┴ └───┘ ┴└┘┴ ┴ ┴ ┴
src └──────┘ └───┘ └┘ ┴
typ ┴ └──────┘ ┴ └───┘ ┴└┘┴ ┴ ┴ ┴
doc └──────┘ └───┘ └┘
2249 (nodup_cons.1 h).1
id └────────┘┴ ┴ ┴
src └────────┘┴ ┴
typ └────────┘┴ ┴ ┴
2250
2251 theorem nodup_of_le {s t : multiset α} (h : s ≤ t) : nodup t → nodup s :=
id └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ └───┘ ┴
src └──────┘ ┴ └───┘ └───┘
typ └──────┘ ┴ ┴ ┴ ┴ └───┘ ┴ └───┘ ┴
doc └──────┘ └───┘ └───┘
2252 le_induction_on h $ λ l₁ l₂, nodup_of_sublist
id └─────────────┘ ┴ └┘ └┘ └──────────────┘
src └─────────────┘ └──────────────┘
typ └─────────────┘ ┴ └┘ └┘ └──────────────┘
2253
2254 theorem not_nodup_pair : ∀ a : α, ¬ nodup (a::a::0) := not_nodup_pair
id ┴ ┴ └───┘ ┴└┘┴└┘ └────────────┘
src ┴ └───┘ └┘ └┘ └────────────┘
typ ┴ ┴ └───┘ ┴└┘┴└┘ └────────────┘
doc └───┘ └┘ └┘
2255
2256 theorem nodup_iff_le {s : multiset α} : nodup s ↔ ∀ a : α, ¬ a::a::0 ≤ s :=
id └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴└┘┴└┘ ┴ ┴
src └──────┘ └───┘ ┴ ┴ └┘ └┘ ┴
typ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴└┘┴└┘ ┴ ┴
doc └──────┘ └───┘ └┘ └┘
2257 quot.induction_on s $ λ l, nodup_iff_sublist.trans $ forall_congr $ λ a,
id └───────────────┘ ┴ ┴ └───────────────┘└────┘ └──────────┘ ┴
src └───────────────┘ └───────────────┘└────┘ └──────────┘
typ └───────────────┘ ┴ ┴ └───────────────┘└────┘ └──────────┘ ┴
2258 not_congr (@repeat_le_coe _ a 2 _).symm
id └───────┘ └───────────┘ ┴ └──┘
src └───────┘ └───────────┘ └──┘
typ └───────┘ └───────────┘ ┴ └──┘
2259
2260 theorem nodup_iff_count_le_one [decidable_eq α] {s : multiset α} : nodup s ↔ ∀ a, count a s ≤ 1 :=
id └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ ┴
src └──────────┘ └──────┘ └───┘ ┴ └───┘ ┴
typ └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ ┴
doc └──────┘ └───┘ └───┘
2261 quot.induction_on s $ λ l, nodup_iff_count_le_one
id └───────────────┘ ┴ ┴ └────────────────────┘
src └───────────────┘ └────────────────────┘
typ └───────────────┘ ┴ ┴ └────────────────────┘
2262
2263 @[simp] theorem count_eq_one_of_mem [decidable_eq α] {a : α} {s : multiset α}
id └──────────┘ ┴ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘
2264 (d : nodup s) (h : a ∈ s) : count a s = 1 :=
id └───┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴
src └───┘ ┴ └───┘ ┴
typ └───┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴
doc └───┘ └───┘
2265 le_antisymm (nodup_iff_count_le_one.1 d a) (count_pos.2 h)
id └─────────┘ └────────────────────┘┴ ┴ ┴ └───────┘┴ ┴
src └─────────┘ └────────────────────┘┴ └───────┘┴
typ └─────────┘ └────────────────────┘┴ ┴ ┴ └───────┘┴ ┴
2266
2267 lemma pairwise_of_nodup {r : α → α → Prop} {s : multiset α} :
id ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ └──────┘ ┴
doc └──────┘
2268 (∀a∈s, ∀b∈s, a ≠ b → r a b) → nodup s → pairwise r s :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ └──────┘ ┴ ┴
src ┴ └───┘ └──────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ └──────┘ ┴ ┴
doc └───┘ └──────┘
2269 quotient.induction_on s $ assume l h hl, ⟨l, rfl, hl.imp_of_mem $ assume a b ha hb, h a ha b hb⟩
id └───────────────────┘ ┴ ┴ ┴ └┘ ┴ └─┘ └┘└─────────┘ ┴ ┴ └┘ └┘ ┴ ┴ └┘ ┴ └┘
src └───────────────────┘ └─┘ └─────────┘
typ └───────────────────┘ ┴ ┴ ┴ └┘ ┴ └─┘ └┘└─────────┘ ┴ ┴ └┘ └┘ ┴ ┴ └┘ ┴ └┘
2270
2271 lemma forall_of_pairwise {r : α → α → Prop} (H : symmetric r) {s : multiset α}
id ┴ ┴ └───────┘ ┴ └──────┘ ┴
src └───────┘ └──────┘
typ ┴ ┴ └───────┘ ┴ └──────┘ ┴
doc └──────┘
2272 (hs : pairwise r s) : (∀a∈s, ∀b∈s, a ≠ b → r a b) :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
2273 let ⟨l, hl₁, hl₂⟩ := hs in hl₁.symm ▸ list.forall_of_pairwise H hl₂
id └─┘ └─┘ └─┘ └┘ └───┘ ┴ └─────────────────────┘ ┴
src └───┘ ┴ └─────────────────────┘
typ └─┘ └─┘ └─┘ └┘ └───┘ ┴ └─────────────────────┘ ┴
2274
2275 theorem nodup_add {s t : multiset α} : nodup (s + t) ↔ nodup s ∧ nodup t ∧ disjoint s t :=
id └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └───┘ ┴ ┴ └───┘ ┴ └───┘ ┴ └──────┘
typ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └───┘ └───┘ └───┘ └──────┘
2276 quotient.induction_on₂ s t $ λ l₁ l₂, nodup_append
id └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘
src └────────────────────┘ └──────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └──────────┘
2277
2278 theorem disjoint_of_nodup_add {s t : multiset α} (d : nodup (s + t)) : disjoint s t :=
id └──────┘ ┴ └───┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └───┘ ┴ └──────┘
typ └──────┘ ┴ └───┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └───┘ └──────┘
2279 (nodup_add.1 d).2.2
id └───────┘┴ ┴ ┴ ┴
src └───────┘┴ ┴ ┴
typ └───────┘┴ ┴ ┴ ┴
2280
2281 theorem nodup_add_of_nodup {s t : multiset α} (d₁ : nodup s) (d₂ : nodup t) : nodup (s + t) ↔ disjoint s t :=
id └──────┘ ┴ └───┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └───┘ └───┘ └───┘ ┴ ┴ └──────┘
typ └──────┘ ┴ └───┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └───┘ └───┘ └───┘ └──────┘
2282 by simp [nodup_add, d₁, d₂]
id └───────┘ └┘ └┘
src └────┘└───────┘└┘ └┘ └─
typ └────┘└───────┘└┘└┘└┘└┘└─
doc └────┘ └┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └─────────────────────────
2283
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2284 theorem nodup_of_nodup_map (f : α → β) {s : multiset α} : nodup (map f s) → nodup s :=
id ┴ ┴ └──────┘ ┴ └───┘ └─┘ ┴ ┴ └───┘ ┴
src └──────┘ └───┘ └─┘ └───┘
typ ┴ ┴ └──────┘ ┴ └───┘ └─┘ ┴ ┴ └───┘ ┴
doc └──────┘ └───┘ └─┘ └───┘
2285 quot.induction_on s $ λ l, nodup_of_nodup_map f
id └───────────────┘ ┴ ┴ └────────────────┘ ┴
src └───────────────┘ └────────────────┘
typ └───────────────┘ ┴ ┴ └────────────────┘ ┴
2286
2287 theorem nodup_map_on {f : α → β} {s : multiset α} : (∀x∈s, ∀y∈s, f x = f y → x = y) →
id ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ ┴
typ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘
2288 nodup s → nodup (map f s) :=
id └───┘ ┴ └───┘ └─┘ ┴ ┴
src └───┘ └───┘ └─┘
typ └───┘ ┴ └───┘ └─┘ ┴ ┴
doc └───┘ └───┘ └─┘
2289 quot.induction_on s $ λ l, nodup_map_on
id └───────────────┘ ┴ ┴ └──────────┘
src └───────────────┘ └──────────┘
typ └───────────────┘ ┴ ┴ └──────────┘
2290
2291 theorem nodup_map {f : α → β} {s : multiset α} (hf : function.injective f) : nodup s → nodup (map f s) :=
id ┴ ┴ └──────┘ ┴ └────────────────┘ ┴ └───┘ ┴ └───┘ └─┘ ┴ ┴
src └──────┘ └────────────────┘ └───┘ └───┘ └─┘
typ ┴ ┴ └──────┘ ┴ └────────────────┘ ┴ └───┘ ┴ └───┘ └─┘ ┴ ┴
doc └──────┘ └───┘ └───┘ └─┘
2292 nodup_map_on (λ x _ y _ h, hf h)
id └──────────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴
src └──────────┘
typ └──────────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴
2293
2294 theorem nodup_filter (p : α → Prop) [decidable_pred p] {s} : nodup s → nodup (filter p s) :=
id ┴ └────────────┘ ┴ └───┘ ┴ └───┘ └────┘ ┴ ┴
src └────────────┘ └───┘ └───┘ └────┘
typ ┴ └────────────┘ ┴ └───┘ ┴ └───┘ └────┘ ┴ ┴
doc └───┘ └───┘ └────┘
2295 quot.induction_on s $ λ l, nodup_filter p
id └───────────────┘ ┴ ┴ └──────────┘ ┴
src └───────────────┘ └──────────┘
typ └───────────────┘ ┴ ┴ └──────────┘ ┴
2296
2297 @[simp] theorem nodup_attach {s : multiset α} : nodup (attach s) ↔ nodup s :=
id └──────┘ ┴ └───┘ └────┘ ┴ ┴ └───┘ ┴
src └──────┘ └───┘ └────┘ ┴ └───┘
typ └──────┘ ┴ └───┘ └────┘ ┴ ┴ └───┘ ┴
doc └──┘ └──────┘ └───┘ └────┘ └───┘
2298 quot.induction_on s $ λ l, nodup_attach
id └───────────────┘ ┴ ┴ └──────────┘
src └───────────────┘ └──────────┘
typ └───────────────┘ ┴ ┴ └──────────┘
2299
2300 theorem nodup_pmap {p : α → Prop} {f : Π a, p a → β} {s : multiset α} {H}
id ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
2301 (hf : ∀ a ha b hb, f a ha = f b hb → a = b) : nodup s → nodup (pmap f s H) :=
id ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └───┘ ┴ └───┘ └──┘ ┴ ┴ ┴
src ┴ ┴ └───┘ └───┘ └──┘
typ ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └───┘ ┴ └───┘ └──┘ ┴ ┴ ┴
doc └───┘ └───┘ └──┘
2302 quot.induction_on s (λ l H, nodup_pmap hf) H
id └───────────────┘ ┴ ┴ ┴ └────────┘ └┘ ┴
src └───────────────┘ └────────┘
typ └───────────────┘ ┴ ┴ ┴ └────────┘ └┘ ┴
2303
2304 instance nodup_decidable [decidable_eq α] (s : multiset α) : decidable (nodup s) :=
id └──────────┘ ┴ └──────┘ ┴ └───────┘ └───┘ ┴
src └──────────┘ └──────┘ └───────┘ └───┘
typ └──────────┘ ┴ └──────┘ ┴ └───────┘ └───┘ ┴
doc └──────┘ └───┘
2305 quotient.rec_on_subsingleton s $ λ l, l.nodup_decidable
id └──────────────────────────┘ ┴ ┴ ┴└──────────────┘
src └──────────────────────────┘ └──────────────┘
typ └──────────────────────────┘ ┴ ┴ ┴└──────────────┘
2306
2307 theorem nodup_erase_eq_filter [decidable_eq α] (a : α) {s} : nodup s → s.erase a = filter (≠ a) s :=
id └──────────┘ ┴ ┴ └───┘ ┴ ┴└────┘ ┴ ┴ └────┘ ┴ ┴ ┴
src └──────────┘ └───┘ └────┘ ┴ └────┘ ┴
typ └──────────┘ ┴ ┴ └───┘ ┴ ┴└────┘ ┴ ┴ └────┘ ┴ ┴ ┴
doc └───┘ └────┘ └────┘
2308 quot.induction_on s $ λ l d, congr_arg coe $ nodup_erase_eq_filter a d
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴ ┴
2309
2310 theorem nodup_erase_of_nodup [decidable_eq α] (a : α) {l} : nodup l → nodup (l.erase a) :=
id └──────────┘ ┴ ┴ └───┘ ┴ └───┘ ┴└────┘ ┴
src └──────────┘ └───┘ └───┘ └────┘
typ └──────────┘ ┴ ┴ └───┘ ┴ └───┘ ┴└────┘ ┴
doc └───┘ └───┘ └────┘
2311 nodup_of_le (erase_le _ _)
id └─────────┘ └──────┘
src └─────────┘ └──────┘
typ └─────────┘ └──────┘
2312
2313 theorem mem_erase_iff_of_nodup [decidable_eq α] {a b : α} {l} (d : nodup l) :
id └──────────┘ ┴ ┴ └───┘ ┴
src └──────────┘ └───┘
typ └──────────┘ ┴ ┴ └───┘ ┴
doc └───┘
2314 a ∈ l.erase b ↔ a ≠ b ∧ a ∈ l :=
id ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └────┘ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴└────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └────┘
2315 by rw nodup_erase_eq_filter b d; simp [and_comm]
id └───────────────────┘ ┴ ┴ └──────┘
src └─┘└───────────────────┘┴ ┴ └────┘└──────┘└─
typ └─┘└───────────────────┘┴┴┴┴ └────┘└──────┘└─
doc └─┘ ┴ ┴ └────┘ └─
txt └─┘ ┴ ┴ └────┘ └─
par └─┘ ┴ ┴ └────┘ └─
pid ┴ ┴ ┴ ┴┴ ┴└
st └──────────────────────────────────────────────
2316
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2317 theorem mem_erase_of_nodup [decidable_eq α] {a : α} {l} (h : nodup l) : a ∉ l.erase a :=
id └──────────┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴└────┘ ┴
src └──────────┘ └───┘ ┴ └────┘
typ └──────────┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴└────┘ ┴
doc └───┘ └────┘
2318 by rw mem_erase_iff_of_nodup h; simp
id └────────────────────┘ ┴
src └─┘└────────────────────┘┴ └────
typ └─┘└────────────────────┘┴┴ └────
doc └─┘ ┴ └────
txt └─┘ ┴ └────
par └─┘ ┴ └────
pid ┴ ┴ └
st └──────────────────────────────────
2319
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2320 theorem nodup_product {s : multiset α} {t : multiset β} : nodup s → nodup t → nodup (product s t) :=
id └──────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ └───┘ └─────┘ ┴ ┴
src └──────┘ └──────┘ └───┘ └───┘ └───┘ └─────┘
typ └──────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ └───┘ └─────┘ ┴ ┴
doc └──────┘ └──────┘ └───┘ └───┘ └───┘ └─────┘
2321 quotient.induction_on₂ s t $ λ l₁ l₂ d₁ d₂, by simp [nodup_product d₁ d₂]
id └────────────────────┘ ┴ ┴ └┘ └┘ └┘ └┘ └───────────┘ └┘ └┘
src └────────────────────┘ └────┘└───────────┘┴ ┴ └─
typ └────────────────────┘ ┴ ┴ └┘ └┘ └┘ └┘ └────┘└───────────┘┴└┘┴└┘└─
doc └────┘ ┴ ┴ └─
txt └────┘ ┴ ┴ └─
par └────┘ ┴ ┴ └─
pid ┴┴ ┴ ┴ ┴└
st └───────────────────────────
2322
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2323 theorem nodup_sigma {σ : α → Type*} {s : multiset α} {t : Π a, multiset (σ a)} :
id ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘
2324 nodup s → (∀ a, nodup (t a)) → nodup (s.sigma t) :=
id └───┘ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴└────┘ ┴
src └───┘ └───┘ └───┘ └────┘
typ └───┘ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴└────┘ ┴
doc └───┘ └───┘ └───┘ └────┘
2325 quot.induction_on s $ assume l₁,
id └───────────────┘ ┴ └┘
src └───────────────┘
typ └───────────────┘ ┴ └┘
2326 begin
st └─────
2327 choose f hf using assume a, quotient.exists_rep (t a),
id └─────────────────┘ ┴
src └────────────────┘ └──┘└─────────────────┘┴ ┴ ┴
typ └────────────────┘ └──┘└─────────────────┘┴ ┴┴ ┴
doc └────────────────┘ └──┘ ┴ ┴ ┴
txt └────────────────┘ └──┘ ┴ ┴ ┴
par └────────────────┘ └──┘ ┴ ┴ ┴
pid └┘└─┘└─────┘ └──┘ ┴ ┴ ┴
st ──────────────────────────────────────────────────────┘└─
2328 rw show t = λ a, f a, from (eq.symm $ funext $ λ a, hf a),
id ┴ ┴ ┴ └─────┘ └────┘ └┘
src └─┘ ┴ ┴┴┴ └──┘ ┴ └─────┘ └─────┘┴ ┴└────┘┴ ┴ └──┘ ┴ ┴
typ └─┘ ┴┴┴┴┴ └──┘┴┴ └─────┘ └─────┘┴ ┴└────┘┴ ┴ └──┘└┘┴ ┴
doc └─┘ ┴ ┴ ┴ └──┘ ┴ └─────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
txt └─┘ ┴ ┴ ┴ └──┘ ┴ └─────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
par └─┘ ┴ ┴ ┴ └──┘ ┴ └─────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
pid ┴ ┴ ┴ ┴ └──┘ ┴ └─────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴
st ──────────────────────────────────────────────────────────┘└─
2329 simpa using nodup_sigma
id └─────────┘
src └──────────┘└─────────┘┴
typ └──────────┘└─────────┘┴
doc └──────────┘ ┴
txt └──────────┘ ┴
par └──────────┘ ┴
pid ┴└────┘ ┴
st ─────────────────────────┘
2330 end
st └─┘
2331
2332 theorem nodup_filter_map (f : α → option β) {s : multiset α}
id ┴ └────┘ ┴ └──────┘ ┴
src └────┘ └──────┘
typ ┴ └────┘ ┴ └──────┘ ┴
doc └──────┘
2333 (H : ∀ (a a' : α) (b : β), b ∈ f a → b ∈ f a' → a = a') :
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘
src ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘
2334 nodup s → nodup (filter_map f s) :=
id └───┘ ┴ └───┘ └────────┘ ┴ ┴
src └───┘ └───┘ └────────┘
typ └───┘ ┴ └───┘ └────────┘ ┴ ┴
doc └───┘ └───┘ └────────┘
2335 quot.induction_on s $ λ l, nodup_filter_map H
id └───────────────┘ ┴ ┴ └──────────────┘ ┴
src └───────────────┘ └──────────────┘
typ └───────────────┘ ┴ ┴ └──────────────┘ ┴
2336
2337 theorem nodup_range (n : ℕ) : nodup (range n) := nodup_range _
id ┴ └───┘ └───┘ ┴ └─────────┘
src ┴ └───┘ └───┘ └─────────┘
typ ┴ └───┘ └───┘ ┴ └─────────┘
doc └───┘ └───┘
2338
2339 theorem nodup_inter_left [decidable_eq α] {s : multiset α} (t) : nodup s → nodup (s ∩ t) :=
id └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴
src └──────────┘ └──────┘ └───┘ └───┘ ┴
typ └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴
doc └──────┘ └───┘ └───┘
2340 nodup_of_le $ inter_le_left _ _
id └─────────┘ └───────────┘
src └─────────┘ └───────────┘
typ └─────────┘ └───────────┘
2341
2342 theorem nodup_inter_right [decidable_eq α] (s) {t : multiset α} : nodup t → nodup (s ∩ t) :=
id └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴
src └──────────┘ └──────┘ └───┘ └───┘ ┴
typ └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴
doc └──────┘ └───┘ └───┘
2343 nodup_of_le $ inter_le_right _ _
id └─────────┘ └────────────┘
src └─────────┘ └────────────┘
typ └─────────┘ └────────────┘
2344
2345 @[simp] theorem nodup_union [decidable_eq α] {s t : multiset α} : nodup (s ∪ t) ↔ nodup s ∧ nodup t :=
id └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴
src └──────────┘ └──────┘ └───┘ ┴ ┴ └───┘ ┴ └───┘
typ └──────────┘ ┴ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ ┴
doc └──┘ └──────┘ └───┘ └───┘ └───┘
2346 ⟨λ h, ⟨nodup_of_le (le_union_left _ _) h, nodup_of_le (le_union_right _ _) h⟩,
id ┴ └─────────┘ └───────────┘ ┴ └─────────┘ └────────────┘ ┴
src └─────────┘ └───────────┘ └─────────┘ └────────────┘
typ ┴ └─────────┘ └───────────┘ ┴ └─────────┘ └────────────┘ ┴
2347 λ ⟨h₁, h₂⟩, nodup_iff_count_le_one.2 $ λ a, by rw [count_union]; exact
id ┴ └────────────────────┘┴ ┴ └─────────┘
src └────────────────────┘┴ └──┘└─────────┘┴ └─────
typ ┴ └────────────────────┘┴ ┴ └──┘└─────────┘┴ └─────
doc └──┘ ┴ └─────
txt └──┘ ┴ └─────
par └──┘ ┴ └─────
pid └┘ ┴ └
st └──────────────┘┴└───────
2348 max_le (nodup_iff_count_le_one.1 h₁ a) (nodup_iff_count_le_one.1 h₂ a)⟩
id └────┘ └┘ └────────────────────┘ └┘ ┴
src ──┘└────┘┴ └─┘ ┴ └┘ └────────────────────┘└─┘ ┴ ┴
typ ──┘└────┘┴ └─┘└┘┴ └┘ └────────────────────┘└─┘└┘┴┴┴
doc ──┘ ┴ └─┘ ┴ └┘ └─┘ ┴ ┴
txt ──┘ ┴ └─┘ ┴ └┘ └─┘ ┴ ┴
par ──┘ ┴ └─┘ ┴ └┘ └─┘ ┴ ┴
pid ──┘ ┴ └─┘ ┴ └┘ └─┘ ┴ ┴
st ────────────────────────────────────────────────────────────────────────┘
2349
2350 @[simp] theorem nodup_powerset {s : multiset α} : nodup (powerset s) ↔ nodup s :=
id └──────┘ ┴ └───┘ └──────┘ ┴ ┴ └───┘ ┴
src └──────┘ └───┘ └──────┘ ┴ └───┘
typ └──────┘ ┴ └───┘ └──────┘ ┴ ┴ └───┘ ┴
doc └──┘ └──────┘ └───┘ └───┘
2351 ⟨λ h, nodup_of_nodup_map _ (nodup_of_le (map_single_le_powerset _) h),
id ┴ └────────────────┘ └─────────┘ └────────────────────┘ ┴
src └────────────────┘ └─────────┘ └────────────────────┘
typ ┴ └────────────────┘ └─────────┘ └────────────────────┘ ┴
2352 quotient.induction_on s $ λ l h,
id └───────────────────┘ ┴ ┴ ┴
src └───────────────────┘
typ └───────────────────┘ ┴ ┴ ┴
2353 by simp; refine list.nodup_map_on _ (nodup_sublists'.2 h); exact
id └───────────────┘ └─────────────┘ ┴
src └──┘ └─────┘└───────────────┘└─┘ └─────────────┘└─┘ ┴ └─────
typ └──┘ └─────┘└───────────────┘└─┘ └─────────────┘└─┘┴┴ └─────
doc └──┘ └─────┘ └─┘ └─┘ ┴ └─────
txt └──┘ └─────┘ └─┘ └─┘ ┴ └─────
par └──┘ └─────┘ └─┘ └─┘ ┴ └─────
pid ┴ └─┘ └─┘ ┴ └
st └──────────────────────────────────────────────────────────────
2354 λ x sx y sy e,
src ─┘ └─────────────
typ ─┘ └─────────────
doc ─┘ └─────────────
txt ─┘ └─────────────
par ─┘ └─────────────
pid ─┘ └─────────────
st ─────────────────
2355 (perm_ext_sublist_nodup h (mem_sublists'.1 sx) (mem_sublists'.1 sy)).1
id └────────────────────┘ ┴ └───────────┘
src ───┘ └────────────────────┘┴ ┴ └─┘ └┘ └───────────┘└─┘ └────
typ ───┘ └────────────────────┘┴┴┴ └─┘ └┘ └───────────┘└─┘ └────
doc ───┘ ┴ ┴ └─┘ └┘ └─┘ └────
txt ───┘ ┴ ┴ └─┘ └┘ └─┘ └────
par ───┘ ┴ ┴ └─┘ └┘ └─┘ └────
pid ───┘ ┴ ┴ └─┘ └┘ └─┘ └────
st ───────────────────────────────────────────────────────────────────────────
2356 (quotient.exact e)⟩
id └────────────┘
src ─────┘ └────────────┘┴ ┴
typ ─────┘ └────────────┘┴ ┴
doc ─────┘ ┴ ┴
txt ─────┘ ┴ ┴
par ─────┘ ┴ ┴
pid ─────┘ ┴ ┴
st ───────────────────────┘
2357
2358 theorem nodup_powerset_len {n : ℕ} {s : multiset α}
id ┴ └──────┘ ┴
src ┴ └──────┘
typ ┴ └──────┘ ┴
doc └──────┘
2359 (h : nodup s) : nodup (powerset_len n s) :=
id └───┘ ┴ └───┘ └──────────┘ ┴ ┴
src └───┘ └───┘ └──────────┘
typ └───┘ ┴ └───┘ └──────────┘ ┴ ┴
doc └───┘ └───┘
2360 nodup_of_le (powerset_len_le_powerset _ _) (nodup_powerset.2 h)
id └─────────┘ └──────────────────────┘ └────────────┘┴ ┴
src └─────────┘ └──────────────────────┘ └────────────┘┴
typ └─────────┘ └──────────────────────┘ └────────────┘┴ ┴
2361
2362 @[simp] lemma nodup_bind {s : multiset α} {t : α → multiset β} :
id └──────┘ ┴ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
2363 nodup (bind s t) ↔ ((∀a∈s, nodup (t a)) ∧ (s.pairwise (λa b, disjoint (t a) (t b)))) :=
id └───┘ └──┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴└───────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
src └───┘ └──┘ ┴ └───┘ ┴ └───────┘ └──────┘
typ └───┘ └──┘ ┴ ┴ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴└───────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └───┘ └──┘ └───┘ └───────┘ └──────┘
2364 have h₁ : ∀a, ∃l:list β, t a = l, from
id ┴ ┴ └──┘ ┴┴ ┴ ┴ ┴ ┴
src ┴ └──┘ ┴ ┴
typ ┴ ┴ └──┘ ┴┴ ┴ ┴ ┴ ┴
2365 assume a, quot.induction_on (t a) $ assume l, ⟨l, rfl⟩,
id ┴ └───────────────┘ ┴ ┴ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ ┴ └───────────────┘ ┴ ┴ ┴ ┴ └─┘
2366 let ⟨t', h'⟩ := classical.axiom_of_choice h₁ in
id └─┘ └┘ └┘ └───────────────────────┘ └┘
src └───────────────────────┘
typ └─┘ └┘ └┘ └───────────────────────┘ └┘
2367 have t = λa, t' a, from funext h',
id ┴ ┴ ┴ ┴ └────┘
src ┴ └────┘
typ ┴ ┴ ┴ ┴ └────┘
2368 have hd : symmetric (λa b, list.disjoint (t' a) (t' b)), from assume a b h, h.symm,
id └───────┘ ┴ ┴ └───────────┘ ┴ ┴ ┴ ┴ ┴ ┴└───┘
src └───────┘ └───────────┘ └───┘
typ └───────┘ ┴ ┴ └───────────┘ ┴ ┴ ┴ ┴ ┴ ┴└───┘
doc └───────────┘
2369 quot.induction_on s $ by simp [this, list.nodup_bind, pairwise_coe_iff_pairwise hd]
id └───────────────┘ ┴ └──┘ └─────────────┘ └───────────────────────┘ └┘
src └───────────────┘ └────┘ └┘└─────────────┘└┘└───────────────────────┘┴ └─
typ └───────────────┘ ┴ └────┘└──┘└┘└─────────────┘└┘└───────────────────────┘┴└┘└─
doc └────┘ └┘ └┘ ┴ └─
txt └────┘ └┘ └┘ ┴ └─
par └────┘ └┘ └┘ ┴ └─
pid ┴┴ └┘ └┘ ┴ ┴└
st └───────────────────────────────────────────────────────────
2370
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2371 theorem nodup_ext {s t : multiset α} : nodup s → nodup t → (s = t ↔ ∀ a, a ∈ s ↔ a ∈ t) :=
id └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───┘ └───┘ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ └───┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └───┘ └───┘
2372 quotient.induction_on₂ s t $ λ l₁ l₂ d₁ d₂, quotient.eq.trans $ perm_ext d₁ d₂
id └────────────────────┘ ┴ ┴ └┘ └┘ └┘ └┘ └─────────┘└────┘ └──────┘ └┘ └┘
src └────────────────────┘ └─────────┘└────┘ └──────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └┘ └┘ └─────────┘└────┘ └──────┘ └┘ └┘
2373
2374 theorem le_iff_subset {s t : multiset α} : nodup s → (s ≤ t ↔ s ⊆ t) :=
id └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───┘ ┴ ┴ ┴
typ └──────┘ ┴ └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └───┘
2375 quotient.induction_on₂ s t $ λ l₁ l₂ d, ⟨subset_of_le, subperm_of_subset_nodup d⟩
id └────────────────────┘ ┴ ┴ └┘ └┘ ┴ └──────────┘ └─────────────────────┘ ┴
src └────────────────────┘ └──────────┘ └─────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ ┴ └──────────┘ └─────────────────────┘ ┴
2376
2377 theorem range_le {m n : ℕ} : range m ≤ range n ↔ m ≤ n :=
id ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
src ┴ └───┘ ┴ └───┘ ┴ ┴
typ ┴ └───┘ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
doc └───┘ └───┘
2378 (le_iff_subset (nodup_range _)).trans range_subset
id └───────────┘ └─────────┘ └───┘ └──────────┘
src └───────────┘ └─────────┘ └───┘ └──────────┘
typ └───────────┘ └─────────┘ └───┘ └──────────┘
2379
2380 theorem mem_sub_of_nodup [decidable_eq α] {a : α} {s t : multiset α} (d : nodup s) :
id └──────────┘ ┴ ┴ └──────┘ ┴ └───┘ ┴
src └──────────┘ └──────┘ └───┘
typ └──────────┘ ┴ ┴ └──────┘ ┴ └───┘ ┴
doc └──────┘ └───┘
2381 a ∈ s - t ↔ a ∈ s ∧ a ∉ t :=
id ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
2382 ⟨λ h, ⟨mem_of_le (sub_le_self _ _) h, λ h',
id ┴ └───────┘ └─────────┘ ┴ └┘
src └───────┘ └─────────┘
typ ┴ └───────┘ └─────────┘ ┴ └┘
2383 by refine count_eq_zero.1 _ h; rw [count_sub a s t, nat.sub_eq_zero_iff_le];
id └───────────┘ ┴ └───────┘ ┴ ┴ ┴ └────────────────────┘
src └─────┘└───────────┘└───┘ └──┘└───────┘┴ ┴ ┴ └┘└────────────────────┘┴
typ └─────┘└───────────┘└───┘┴ └──┘└───────┘┴┴┴┴┴┴└┘└────────────────────┘┴
doc └─────┘ └───┘ └──┘ ┴ ┴ ┴ └┘ ┴
txt └─────┘ └───┘ └──┘ ┴ ┴ ┴ └┘ ┴
par └─────┘ └───┘ └──┘ ┴ ┴ ┴ └┘ ┴
pid ┴ └───┘ └┘ ┴ ┴ ┴ └┘ ┴
st └───────────────────────────────┘└─────────────┘└──────────────────────┘┴└─
2384 exact le_trans (nodup_iff_count_le_one.1 d _) (count_pos.2 h')⟩,
id └──────┘ └────────────────────┘ ┴ └───────┘ └┘
src └────┘└──────┘┴ └────────────────────┘└─┘ └──┘ └───────┘└─┘ ┴
typ └────┘└──────┘┴ └────────────────────┘└─┘┴└──┘ └───────┘└─┘└┘┴
doc └────┘ ┴ └─┘ └──┘ └─┘ ┴
txt └────┘ ┴ └─┘ └──┘ └─┘ ┴
par └────┘ ┴ └─┘ └──┘ └─┘ ┴
pid ┴ ┴ └─┘ └──┘ └─┘ ┴
st ──────────────────────────────────────────────────────────────────┘
2385 λ ⟨h₁, h₂⟩, or.resolve_right (mem_add.1 $ mem_of_le (le_sub_add _ _) h₁) h₂⟩
id ┴└┘ └┘ └──────────────┘ └─────┘┴ └───────┘ └────────┘
src └──────────────┘ └─────┘┴ └───────┘ └────────┘
typ ┴└┘ └┘ └──────────────┘ └─────┘┴ └───────┘ └────────┘
2386
2387 lemma map_eq_map_of_bij_of_nodup (f : α → γ) (g : β → γ) {s : multiset α} {t : multiset β}
id ┴ ┴ ┴ ┴ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ ┴ ┴ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
2388 (hs : s.nodup) (ht : t.nodup) (i : Πa∈s, β)
id ┴└────┘ ┴└────┘ ┴ ┴ ┴
src └────┘ └────┘
typ ┴└────┘ ┴└────┘ ┴ ┴ ┴
doc └────┘ └────┘
2389 (hi : ∀a ha, i a ha ∈ t) (h : ∀a ha, f a = g (i a ha))
id ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ └┘
src ┴ ┴
typ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ └┘
2390 (i_inj : ∀a₁ a₂ ha₁ ha₂, i a₁ ha₁ = i a₂ ha₂ → a₁ = a₂)
id └┘ └┘ └─┘ └─┘ ┴ └┘ └─┘ ┴ ┴ └┘ └─┘ └┘ ┴ └┘
src ┴ ┴
typ └┘ └┘ └─┘ └─┘ ┴ └┘ └─┘ ┴ ┴ └┘ └─┘ └┘ ┴ └┘
2391 (i_surj : ∀b∈t, ∃a ha, b = i a ha) :
id ┴ ┴ ┴┴ └┘┴ ┴ ┴ ┴ ┴ └┘
src ┴ ┴ ┴
typ ┴ ┴ ┴┴ └┘┴ ┴ ┴ ┴ ┴ └┘
2392 s.map f = t.map g :=
id ┴└──┘ ┴ ┴ ┴└──┘ ┴
src └──┘ ┴ └──┘
typ ┴└──┘ ┴ ┴ ┴└──┘ ┴
doc └──┘ └──┘
2393 have t = s.attach.map (λ x, i x.1 x.2),
id ┴ ┴ ┴└─────┘└──┘ ┴ ┴ ┴┴ ┴┴
src ┴ └─────┘└──┘ ┴ ┴
typ ┴ ┴ ┴└─────┘└──┘ ┴ ┴ ┴┴ ┴┴
doc └─────┘└──┘
2394 from (nodup_ext ht (nodup_map
id └───────┘ └┘ └───────┘
src └───────┘ └───────┘
typ └───────┘ └┘ └───────┘
2395 (show function.injective (λ x : {x // x ∈ s}, i x.1 x.2), from λ x y hxy,
id └────────────────┘ ┴┴ ┴ ┴ ┴ ┴ ┴┴ ┴┴ ┴ ┴ └─┘
src └────────────────┘ ┴ ┴ ┴ ┴
typ └────────────────┘ ┴┴ ┴ ┴ ┴ ┴ ┴┴ ┴┴ ┴ ┴ └─┘
2396 subtype.eq (i_inj x.1 y.1 x.2 y.2 hxy))
id └────────┘ └───┘ ┴┴ ┴┴ ┴┴ ┴┴ └─┘
src └────────┘ ┴ ┴ ┴ ┴
typ └────────┘ └───┘ ┴┴ ┴┴ ┴┴ ┴┴ └─┘
2397 (nodup_attach.2 hs))).2
id └──────────┘┴ └┘ ┴
src └──────────┘┴ ┴
typ └──────────┘┴ └┘ ┴
2398 (λ x, by simp only [mem_map, true_and, subtype.exists, eq_comm, mem_attach];
id ┴ └─────┘ └──────┘ └────────────┘ └─────┘ └────────┘
src └─────────┘└─────┘└┘└──────┘└┘└────────────┘└┘└─────┘└┘└────────┘┴
typ ┴ └─────────┘└─────┘└┘└──────┘└┘└────────────┘└┘└─────┘└┘└────────┘┴
doc └─────────┘ └┘ └┘ └┘ └┘ ┴
txt └─────────┘ └┘ └┘ └┘ └┘ ┴
par └─────────┘ └┘ └┘ └┘ └┘ ┴
pid ┴└──┘└┘ └┘ └┘ └┘ └┘ ┴
st └────────────────────────────────────────────────────────────────────
2399 exact ⟨i_surj _, λ ⟨y, hy⟩, hy.snd.symm ▸ hi _ _⟩),
id └────┘ └┘ └──┘└───┘ ┴ └┘
src └────┘ └──┘ └┘ └┘ └─┘ └──┘└───┘┴┴┴ └───┘
typ └────┘ └────┘└──┘ └┘ └┘└┘└─┘ └──┘└───┘┴┴┴└┘└───┘
doc └────┘ └──┘ └┘ └┘ └─┘ ┴ ┴ └───┘
txt └────┘ └──┘ └┘ └┘ └─┘ ┴ ┴ └───┘
par └────┘ └──┘ └┘ └┘ └─┘ ┴ ┴ └───┘
pid ┴ └──┘ └┘ └┘ └─┘ ┴ ┴ └───┘
st ──────────────────────────────────────────────────────┘
2400 calc s.map f = s.pmap (λ x _, f x) (λ _, id) : by rw [pmap_eq_map]
id ┴└──┘ ┴ ┴└───┘ ┴ ┴ ┴ ┴ ┴ └┘ └─────────┘
src └──┘ └───┘ └┘ └──┘└─────────┘└┘
typ ┴└──┘ ┴ ┴└───┘ ┴ ┴ ┴ ┴ ┴ └┘ └──┘└─────────┘└┘
doc └──┘ └───┘ └──┘ └┘
txt └──┘ └┘
par └──┘ └┘
pid └┘ ┴┴
st └──────────────┘┴┴
2401 ... = s.attach.map (λ x, f x.1) : by rw [pmap_eq_map_attach]
id ┴└─────┘└──┘ ┴ ┴ ┴┴ └────────────────┘
src └─────┘└──┘ ┴ └──┘└────────────────┘└┘
typ ┴└─────┘└──┘ ┴ ┴ ┴┴ └──┘└────────────────┘└┘
doc └─────┘└──┘ └──┘ └┘
txt └──┘ └┘
par └──┘ └┘
pid └┘ ┴┴
st └─────────────────────┘┴┴
2402 ... = t.map g : by rw [this, multiset.map_map]; exact map_congr (λ x _, h _ _)
id ┴└──┘ ┴ └──┘ └──────────────┘ └───────┘ ┴
src └──┘ └──┘ └┘└──────────────┘┴ └────┘└───────┘┴ └────┘ └─────
typ ┴└──┘ ┴ └──┘└──┘└┘└──────────────┘┴ └────┘└───────┘┴ └────┘┴└─────
doc └──┘ └──┘ └┘ ┴ └────┘ ┴ └────┘ └─────
txt └──┘ └┘ ┴ └────┘ ┴ └────┘ └─────
par └──┘ └┘ ┴ └────┘ ┴ └────┘ └─────
pid └┘ └┘ ┴ ┴ ┴ └────┘ └───┘└
st └───────┘└────────────────┘┴└────────────────────────────────
2403
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2404 section
2405 variable [decidable_eq α]
id └──────────┘
src └──────────┘
typ └──────────┘
2406
2407 /- erase_dup -/
2408
2409 /-- `erase_dup s` removes duplicates from `s`, yielding a `nodup` multiset. -/
2410 def erase_dup (s : multiset α) : multiset α :=
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
2411 quot.lift_on s (λ l, (l.erase_dup : multiset α))
id └──────────┘ ┴ ┴ ┴└────────┘ └──────┘ ┴
src └──────────┘ └────────┘ └──────┘
typ └──────────┘ ┴ ┴ ┴└────────┘ └──────┘ ┴
doc └────────┘ └──────┘
2412 (λ s t p, quot.sound (perm_erase_dup_of_perm p))
id ┴ ┴ ┴ └────────┘ └────────────────────┘ ┴
src └────────┘ └────────────────────┘
typ ┴ ┴ ┴ └────────┘ └────────────────────┘ ┴
2413
2414 @[simp] theorem coe_erase_dup (l : list α) : @erase_dup α _ l = l.erase_dup := rfl
id └──┘ ┴ └───────┘ ┴ ┴ ┴ ┴└────────┘ └─┘
src └──┘ └───────┘ ┴ └────────┘ └─┘
typ └──┘ ┴ └───────┘ ┴ ┴ ┴ ┴└────────┘ └─┘
doc └──┘ └───────┘ └────────┘
2415
2416 @[simp] theorem erase_dup_zero : @erase_dup α _ 0 = 0 := rfl
id └───────┘ ┴ ┴ └─┘
src └───────┘ ┴ └─┘
typ └───────┘ ┴ ┴ └─┘
doc └──┘ └───────┘
2417
2418 @[simp] theorem mem_erase_dup {a : α} {s : multiset α} : a ∈ erase_dup s ↔ a ∈ s :=
id ┴ └──────┘ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └───────┘ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └───────┘
2419 quot.induction_on s $ λ l, mem_erase_dup
id └───────────────┘ ┴ ┴ └───────────┘
src └───────────────┘ └───────────┘
typ └───────────────┘ ┴ ┴ └───────────┘
2420
2421 @[simp] theorem erase_dup_cons_of_mem {a : α} {s : multiset α} : a ∈ s →
id ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
2422 erase_dup (a::s) = erase_dup s :=
id └───────┘ ┴└┘┴ ┴ └───────┘ ┴
src └───────┘ └┘ ┴ └───────┘
typ └───────┘ ┴└┘┴ ┴ └───────┘ ┴
doc └───────┘ └┘ └───────┘
2423 quot.induction_on s $ λ l m, @congr_arg _ _ _ _ coe $ erase_dup_cons_of_mem m
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────────┘ ┴
2424
2425 @[simp] theorem erase_dup_cons_of_not_mem {a : α} {s : multiset α} : a ∉ s →
id ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
2426 erase_dup (a::s) = a :: erase_dup s :=
id └───────┘ ┴└┘┴ ┴ ┴ └┘ └───────┘ ┴
src └───────┘ └┘ ┴ └┘ └───────┘
typ └───────┘ ┴└┘┴ ┴ ┴ └┘ └───────┘ ┴
doc └───────┘ └┘ └┘ └───────┘
2427 quot.induction_on s $ λ l m, congr_arg coe $ erase_dup_cons_of_not_mem m
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────────────┘ ┴
2428
2429 theorem erase_dup_le (s : multiset α) : erase_dup s ≤ s :=
id └──────┘ ┴ └───────┘ ┴ ┴ ┴
src └──────┘ └───────┘ ┴
typ └──────┘ ┴ └───────┘ ┴ ┴ ┴
doc └──────┘ └───────┘
2430 quot.induction_on s $ λ l, subperm_of_sublist $ erase_dup_sublist _
id └───────────────┘ ┴ ┴ └────────────────┘ └───────────────┘
src └───────────────┘ └────────────────┘ └───────────────┘
typ └───────────────┘ ┴ ┴ └────────────────┘ └───────────────┘
2431
2432 theorem erase_dup_subset (s : multiset α) : erase_dup s ⊆ s :=
id └──────┘ ┴ └───────┘ ┴ ┴ ┴
src └──────┘ └───────┘ ┴
typ └──────┘ ┴ └───────┘ ┴ ┴ ┴
doc └──────┘ └───────┘
2433 subset_of_le $ erase_dup_le _
id └──────────┘ └──────────┘
src └──────────┘ └──────────┘
typ └──────────┘ └──────────┘
2434
2435 theorem subset_erase_dup (s : multiset α) : s ⊆ erase_dup s :=
id └──────┘ ┴ ┴ ┴ └───────┘ ┴
src └──────┘ ┴ └───────┘
typ └──────┘ ┴ ┴ ┴ └───────┘ ┴
doc └──────┘ └───────┘
2436 λ a, mem_erase_dup.2
id ┴ └───────────┘┴
src └───────────┘┴
typ ┴ └───────────┘┴
2437
2438 @[simp] theorem erase_dup_subset' {s t : multiset α} : erase_dup s ⊆ t ↔ s ⊆ t :=
id └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───────┘ ┴ ┴ ┴
typ └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └───────┘
2439 ⟨subset.trans (subset_erase_dup _), subset.trans (erase_dup_subset _)⟩
id └──────────┘ └──────────────┘ └──────────┘ └──────────────┘
src └──────────┘ └──────────────┘ └──────────┘ └──────────────┘
typ └──────────┘ └──────────────┘ └──────────┘ └──────────────┘
2440
2441 @[simp] theorem subset_erase_dup' {s t : multiset α} : s ⊆ erase_dup t ↔ s ⊆ t :=
id └──────┘ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └───────┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └───────┘
2442 ⟨λ h, subset.trans h (erase_dup_subset _), λ h, subset.trans h (subset_erase_dup _)⟩
id ┴ └──────────┘ ┴ └──────────────┘ ┴ └──────────┘ ┴ └──────────────┘
src └──────────┘ └──────────────┘ └──────────┘ └──────────────┘
typ ┴ └──────────┘ ┴ └──────────────┘ ┴ └──────────┘ ┴ └──────────────┘
2443
2444 @[simp] theorem nodup_erase_dup (s : multiset α) : nodup (erase_dup s) :=
id └──────┘ ┴ └───┘ └───────┘ ┴
src └──────┘ └───┘ └───────┘
typ └──────┘ ┴ └───┘ └───────┘ ┴
doc └──┘ └──────┘ └───┘ └───────┘
2445 quot.induction_on s nodup_erase_dup
id └───────────────┘ ┴ └─────────────┘
src └───────────────┘ └─────────────┘
typ └───────────────┘ ┴ └─────────────┘
2446
2447 theorem erase_dup_eq_self {s : multiset α} : erase_dup s = s ↔ nodup s :=
id └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ └───┘ ┴
src └──────┘ └───────┘ ┴ ┴ └───┘
typ └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ └───┘ ┴
doc └──────┘ └───────┘ └───┘
2448 ⟨λ e, e ▸ nodup_erase_dup s,
id ┴ ┴ ┴ └─────────────┘ ┴
src ┴ └─────────────┘
typ ┴ ┴ ┴ └─────────────┘ ┴
2449 quot.induction_on s $ λ l h, congr_arg coe $ erase_dup_eq_self.2 h⟩
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────┘┴ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────┘┴
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────┘┴ ┴
2450
2451 theorem erase_dup_eq_zero {s : multiset α} : erase_dup s = 0 ↔ s = 0 :=
id └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───────┘ ┴ ┴ ┴
typ └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └───────┘
2452 ⟨λ h, eq_zero_of_subset_zero $ h ▸ subset_erase_dup _,
id ┴ └────────────────────┘ ┴ ┴ └──────────────┘
src └────────────────────┘ ┴ └──────────────┘
typ ┴ └────────────────────┘ ┴ ┴ └──────────────┘
2453 λ h, h.symm ▸ erase_dup_zero⟩
id ┴ ┴└───┘ ┴ └────────────┘
src └───┘ ┴ └────────────┘
typ ┴ ┴└───┘ ┴ └────────────┘
2454
2455 @[simp] theorem erase_dup_singleton {a : α} : erase_dup (a :: 0) = a :: 0 :=
id ┴ └───────┘ ┴ └┘ ┴ ┴ └┘
src └───────┘ └┘ ┴ └┘
typ ┴ └───────┘ ┴ └┘ ┴ ┴ └┘
doc └──┘ └───────┘ └┘ └┘
2456 erase_dup_eq_self.2 $ nodup_singleton _
id └───────────────┘┴ └─────────────┘
src └───────────────┘┴ └─────────────┘
typ └───────────────┘┴ └─────────────┘
2457
2458 theorem le_erase_dup {s t : multiset α} : s ≤ erase_dup t ↔ s ≤ t ∧ nodup s :=
id └──────┘ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴
src └──────┘ ┴ └───────┘ ┴ ┴ ┴ └───┘
typ └──────┘ ┴ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ ┴
doc └──────┘ └───────┘ └───┘
2459 ⟨λ h, ⟨le_trans h (erase_dup_le _), nodup_of_le h (nodup_erase_dup _)⟩,
id ┴ └──────┘ ┴ └──────────┘ └─────────┘ ┴ └─────────────┘
src └──────┘ └──────────┘ └─────────┘ └─────────────┘
typ ┴ └──────┘ ┴ └──────────┘ └─────────┘ ┴ └─────────────┘
2460 λ ⟨l, d⟩, (le_iff_subset d).2 $ subset.trans (subset_of_le l) (subset_erase_dup _)⟩
id ┴┴ ┴ └───────────┘ ┴ └──────────┘ └──────────┘ └──────────────┘
src └───────────┘ ┴ └──────────┘ └──────────┘ └──────────────┘
typ ┴┴ ┴ └───────────┘ ┴ └──────────┘ └──────────┘ └──────────────┘
2461
2462 theorem erase_dup_ext {s t : multiset α} : erase_dup s = erase_dup t ↔ ∀ a, a ∈ s ↔ a ∈ t :=
id └──────┘ ┴ └───────┘ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───────┘ ┴ └───────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ └───────┘ ┴ ┴ └───────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └───────┘ └───────┘
2463 by simp [nodup_ext]
id └───────┘
src └────┘└───────┘└─
typ └────┘└───────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────────────
2464
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2465 theorem erase_dup_map_erase_dup_eq [decidable_eq β] (f : α → β) (s : multiset α) :
id └──────────┘ ┴ ┴ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
2466 erase_dup (map f (erase_dup s)) = erase_dup (map f s) := by simp [erase_dup_ext]
id └───────┘ └─┘ ┴ └───────┘ ┴ ┴ └───────┘ └─┘ ┴ ┴ └───────────┘
src └───────┘ └─┘ └───────┘ ┴ └───────┘ └─┘ └────┘└───────────┘└─
typ └───────┘ └─┘ ┴ └───────┘ ┴ ┴ └───────┘ └─┘ ┴ ┴ └────┘└───────────┘└─
doc └───────┘ └─┘ └───────┘ └───────┘ └─┘ └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────────────────
2467
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
2468 /- finset insert -/
src ────────────────────
typ ────────────────────
doc ────────────────────
txt ────────────────────
par ────────────────────
pid ────────────────────
st ────────────────────
2469
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2470 /-- `ndinsert a s` is the lift of the list `insert` operation. This operation
2471 does not respect multiplicities, unlike `cons`, but it is suitable as
2472 an insert operation on `finset`. -/
2473 def ndinsert (a : α) (s : multiset α) : multiset α :=
id ┴ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ ┴ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
2474 quot.lift_on s (λ l, (l.insert a : multiset α))
id └──────────┘ ┴ ┴ ┴└─────┘ ┴ └──────┘ ┴
src └──────────┘ └─────┘ └──────┘
typ └──────────┘ ┴ ┴ ┴└─────┘ ┴ └──────┘ ┴
doc └──────┘
2475 (λ s t p, quot.sound (perm_insert a p))
id ┴ ┴ ┴ └────────┘ └─────────┘ ┴ ┴
src └────────┘ └─────────┘
typ ┴ ┴ ┴ └────────┘ └─────────┘ ┴ ┴
2476
2477 @[simp] theorem coe_ndinsert (a : α) (l : list α) : ndinsert a l = (insert a l : list α) := rfl
id ┴ └──┘ ┴ └──────┘ ┴ ┴ ┴ └────┘ ┴ ┴ └──┘ ┴ └─┘
src └──┘ └──────┘ ┴ └────┘ └──┘ └─┘
typ ┴ └──┘ ┴ └──────┘ ┴ ┴ ┴ └────┘ ┴ ┴ └──┘ ┴ └─┘
doc └──┘ └──────┘
2478
2479 @[simp] theorem ndinsert_zero (a : α) : ndinsert a 0 = a::0 := rfl
id ┴ └──────┘ ┴ ┴ ┴└┘ └─┘
src └──────┘ ┴ └┘ └─┘
typ ┴ └──────┘ ┴ ┴ ┴└┘ └─┘
doc └──┘ └──────┘ └┘
2480
2481 @[simp] theorem ndinsert_of_mem {a : α} {s : multiset α} : a ∈ s → ndinsert a s = s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──────┘ ┴
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──────┘
2482 quot.induction_on s $ λ l h, congr_arg coe $ insert_of_mem h
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └───────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────┘ ┴
2483
2484 @[simp] theorem ndinsert_of_not_mem {a : α} {s : multiset α} : a ∉ s → ndinsert a s = a :: s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ └──────┘ ┴ └┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘ ┴
doc └──┘ └──────┘ └──────┘ └┘
2485 quot.induction_on s $ λ l h, congr_arg coe $ insert_of_not_mem h
id └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────┘ ┴
src └───────────────┘ └───────┘ └─┘ └───────────────┘
typ └───────────────┘ ┴ ┴ ┴ └───────┘ └─┘ └───────────────┘ ┴
2486
2487 @[simp] theorem mem_ndinsert {a b : α} {s : multiset α} : a ∈ ndinsert b s ↔ a = b ∨ a ∈ s :=
id ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──────┘
2488 quot.induction_on s $ λ l, mem_insert_iff
id └───────────────┘ ┴ ┴ └────────────┘
src └───────────────┘ └────────────┘
typ └───────────────┘ ┴ ┴ └────────────┘
2489
2490 @[simp] theorem le_ndinsert_self (a : α) (s : multiset α) : s ≤ ndinsert a s :=
id ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ └──────┘
typ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘
2491 quot.induction_on s $ λ l, subperm_of_sublist $ sublist_of_suffix $ suffix_insert _ _
id └───────────────┘ ┴ ┴ └────────────────┘ └───────────────┘ └───────────┘
src └───────────────┘ └────────────────┘ └───────────────┘ └───────────┘
typ └───────────────┘ ┴ ┴ └────────────────┘ └───────────────┘ └───────────┘
2492
2493 @[simp] theorem mem_ndinsert_self (a : α) (s : multiset α) : a ∈ ndinsert a s :=
id ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ └──────┘
typ ┴ └──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘
2494 mem_ndinsert.2 (or.inl rfl)
id └──────────┘┴ └────┘ └─┘
src └──────────┘┴ └────┘ └─┘
typ └──────────┘┴ └────┘ └─┘
2495
2496 @[simp] theorem mem_ndinsert_of_mem {a b : α} {s : multiset α} (h : a ∈ s) : a ∈ ndinsert b s :=
id ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ ┴ ┴ └──────┘
typ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──┘ └──────┘ └──────┘
2497 mem_ndinsert.2 (or.inr h)
id └──────────┘┴ └────┘ ┴
src └──────────┘┴ └────┘
typ └──────────┘┴ └────┘ ┴
2498
2499 @[simp] theorem length_ndinsert_of_mem {a : α} [decidable_eq α] {s : multiset α} (h : a ∈ s) :
id ┴ └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────────┘ └──────┘ ┴
typ ┴ └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
2500 card (ndinsert a s) = card s :=
id └──┘ └──────┘ ┴ ┴ ┴ └──┘ ┴
src └──┘ └──────┘ ┴ └──┘
typ └──┘ └──────┘ ┴ ┴ ┴ └──┘ ┴
doc └──┘ └──────┘ └──┘
2501 by simp [h]
id ┴
src └────┘ └─
typ └────┘┴└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────
2502
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2503 @[simp] theorem length_ndinsert_of_not_mem {a : α} [decidable_eq α] {s : multiset α} (h : a ∉ s) :
id ┴ └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────────┘ └──────┘ ┴
typ ┴ └──────────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘
2504 card (ndinsert a s) = card s + 1 :=
id └──┘ └──────┘ ┴ ┴ ┴ └──┘ ┴ ┴
src └──┘ └──────┘ ┴ └──┘ ┴
typ └──┘ └──────┘ ┴ ┴ ┴ └──┘ ┴ ┴
doc └──┘ └──────┘ └──┘
2505 by simp [h]
id ┴
src └────┘ └─
typ └────┘┴└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └─────────
2506
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2507 theorem erase_dup_cons {a : α} {s : multiset α} :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──────┘
2508 erase_dup (a::s) = ndinsert a (erase_dup s) :=
id └───────┘ ┴└┘┴ ┴ └──────┘ ┴ └───────┘ ┴
src └───────┘ └┘ ┴ └──────┘ └───────┘
typ └───────┘ ┴└┘┴ ┴ └──────┘ ┴ └───────┘ ┴
doc └───────┘ └┘ └──────┘ └───────┘
2509 by by_cases a ∈ s; simp [h]
id ┴ ┴ ┴ ┴
src └───────┘ ┴┴┴ └────┘ └─
typ └───────┘┴┴┴┴┴ └────┘┴└─
doc └───────┘ ┴ ┴ └────┘ └─
txt └───────┘ ┴ ┴ └────┘ └─
par └───────┘ ┴ ┴ └────┘ └─
pid ┴ ┴ ┴ ┴┴ ┴└
st └─────────────────────────
2510
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2511 theorem nodup_ndinsert (a : α) {s : multiset α} : nodup s → nodup (ndinsert a s) :=
id ┴ └──────┘ ┴ └───┘ ┴ └───┘ └──────┘ ┴ ┴
src └──────┘ └───┘ └───┘ └──────┘
typ ┴ └──────┘ ┴ └───┘ ┴ └───┘ └──────┘ ┴ ┴
doc └──────┘ └───┘ └───┘ └──────┘
2512 quot.induction_on s $ λ l, nodup_insert
id └───────────────┘ ┴ ┴ └──────────┘
src └───────────────┘ └──────────┘
typ └───────────────┘ ┴ ┴ └──────────┘
2513
2514 theorem ndinsert_le {a : α} {s t : multiset α} : ndinsert a s ≤ t ↔ s ≤ t ∧ a ∈ t :=
id ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ ┴ ┴ ┴ ┴ ┴
typ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘
2515 ⟨λ h, ⟨le_trans (le_ndinsert_self _ _) h, mem_of_le h (mem_ndinsert_self _ _)⟩,
id ┴ └──────┘ └──────────────┘ ┴ └───────┘ ┴ └───────────────┘
src └──────┘ └──────────────┘ └───────┘ └───────────────┘
typ ┴ └──────┘ └──────────────┘ ┴ └───────┘ ┴ └───────────────┘
2516 λ ⟨l, m⟩, if h : a ∈ s then by simp [h, l] else
id ┴ └┘ ┴ ┴ ┴ ┴ ┴
src └┘ ┴ └────┘ └┘ └┘
typ ┴ └┘ ┴ ┴ ┴ └────┘┴└┘┴└┘
doc └────┘ └┘ └┘
txt └────┘ └┘ └┘
par └────┘ └┘ └┘
pid ┴┴ └┘ ┴┴
st └───────────┘
2517 by rw [ndinsert_of_not_mem h, ← cons_erase m, cons_le_cons_iff,
id └─────────────────┘ ┴ └────────┘ ┴ └──────────────┘
src └──┘└─────────────────┘┴ └──┘└────────┘┴ └┘└──────────────┘└─
typ └──┘└─────────────────┘┴┴└──┘└────────┘┴┴└┘└──────────────┘└─
doc └──┘ ┴ └──┘ ┴ └┘ └─
txt └──┘ ┴ └──┘ ┴ └┘ └─
par └──┘ ┴ └──┘ ┴ └┘ └─
pid └┘ ┴ └──┘ ┴ └┘ └─
st └────────────────────────┘└──────────────┘└────────────────┘└─
2518 ← le_cons_of_not_mem h, cons_erase m]; exact l⟩
id └────────────────┘ ┴ └────────┘ ┴ ┴
src ───────────┘└────────────────┘┴ └┘└────────┘┴ ┴ └────┘
typ ───────────┘└────────────────┘┴┴└┘└────────┘┴┴┴ └────┘┴
doc ───────────┘ ┴ └┘ ┴ ┴ └────┘
txt ───────────┘ ┴ └┘ ┴ ┴ └────┘
par ───────────┘ ┴ └┘ ┴ ┴ └────┘
pid ───────────┘ ┴ └┘ ┴ ┴ ┴
st ───────────────────────────────┘└────────────┘┴└───────┘
2519
2520 lemma attach_ndinsert (a : α) (s : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──────┘
2521 (s.ndinsert a).attach =
id ┴└───────┘ ┴ └────┘ ┴
src └───────┘ └────┘ ┴
typ ┴└───────┘ ┴ └────┘ ┴
doc └───────┘ └────┘
2522 ndinsert ⟨a, mem_ndinsert_self a s⟩ (s.attach.map $ λp, ⟨p.1, mem_ndinsert_of_mem p.2⟩) :=
id └──────┘ ┴ └───────────────┘ ┴ ┴ ┴└─────┘└──┘ ┴ ┴┴ └─────────────────┘ ┴┴
src └──────┘ └───────────────┘ └─────┘└──┘ ┴ └─────────────────┘ ┴
typ └──────┘ ┴ └───────────────┘ ┴ ┴ ┴└─────┘└──┘ ┴ ┴┴ └─────────────────┘ ┴┴
doc └──────┘ └─────┘└──┘
2523 have eq : ∀h : ∀(p : {x // x ∈ s}), p.1 ∈ s,
id ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴
2524 (λ (p : {x // x ∈ s}), ⟨p.val, h p⟩ : {x // x ∈ s} → {x // x ∈ s}) = id, from
id ┴┴ ┴ ┴ ┴ ┴└──┘ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ └┘
src ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ └┘
typ ┴┴ ┴ ┴ ┴ ┴└──┘ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ └┘
2525 assume h, funext $ assume p, subtype.eq rfl,
id ┴ └────┘ ┴ └────────┘ └─┘
src └────┘ └────────┘ └─┘
typ ┴ └────┘ ┴ └────────┘ └─┘
2526 have ∀t (eq : s.ndinsert a = t), t.attach = ndinsert ⟨a, eq ▸ mem_ndinsert_self a s⟩
id ┴ ┴└───────┘ ┴ ┴ ┴ ┴└─────┘ ┴ └──────┘ ┴ └┘ ┴ └───────────────┘ ┴ ┴
src └───────┘ ┴ └─────┘ ┴ └──────┘ └┘ ┴ └───────────────┘
typ ┴ ┴└───────┘ ┴ ┴ ┴ ┴└─────┘ ┴ └──────┘ ┴ └┘ ┴ └───────────────┘ ┴ ┴
doc └───────┘ └─────┘ └──────┘
2527 (s.attach.map $ λp, ⟨p.1, eq ▸ mem_ndinsert_of_mem p.2⟩),
id ┴└─────┘└──┘ ┴ ┴┴ └┘ ┴ └─────────────────┘ ┴┴
src └─────┘└──┘ ┴ └┘ ┴ └─────────────────┘ ┴
typ ┴└─────┘└──┘ ┴ ┴┴ └┘ ┴ └─────────────────┘ ┴┴
doc └─────┘└──┘
2528 begin
st └─────
2529 intros t ht,
src └─────────┘
typ └─────────┘
doc └─────────┘
txt └─────────┘
par └─────────┘
pid └───┘
st ────────────┘└─
2530 by_cases a ∈ s,
id ┴ ┴ ┴
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────┘└─
2531 { rw [ndinsert_of_mem h] at ht,
id └─────────────┘ ┴
src └──┘└─────────────┘┴ └─────┘
typ └──┘└─────────────┘┴┴└─────┘
doc └──┘ ┴ └─────┘
txt └──┘ ┴ └─────┘
par └──┘ ┴ └─────┘
pid └┘ ┴ ┴└────┘
st ───┘└───────────────────┘┴└────┘└─
2532 subst ht,
id └┘
src └────┘
typ └────┘└┘
doc └────┘
txt └────┘
par └────┘
pid ┴
st ───────────┘└─
2533 rw [eq, map_id, ndinsert_of_mem (mem_attach _ _)] },
id └┘ └────┘ └─────────────┘ └────────┘
src └──┘└┘└┘└────┘└┘└─────────────┘┴ └────────┘└─────┘
typ └──┘└┘└┘└────┘└┘└─────────────┘┴ └────────┘└─────┘
doc └──┘ └┘ └┘ ┴ └─────┘
txt └──┘ └┘ └┘ ┴ └─────┘
par └──┘ └┘ └┘ ┴ └─────┘
pid └┘ └┘ └┘ ┴ └────┘┴
st ─────────┘└──────┘└────────────────────────────────┘┴┴└┘└
2534 { rw [ndinsert_of_not_mem h] at ht,
id └─────────────────┘ ┴
src └──┘└─────────────────┘┴ └─────┘
typ └──┘└─────────────────┘┴┴└─────┘
doc └──┘ ┴ └─────┘
txt └──┘ ┴ └─────┘
par └──┘ ┴ └─────┘
pid └┘ ┴ ┴└────┘
st ────────────────────────────┘┴└────┘└─
2535 subst ht,
id └┘
src └────┘
typ └────┘└┘
doc └────┘
txt └────┘
par └────┘
pid ┴
st ───────────┘└─
2536 simp [attach_cons, h] }
id └─────────┘ ┴
src └────┘└─────────┘└┘ └┘
typ └────┘└─────────┘└┘┴└┘
doc └────┘ └┘ └┘
txt └────┘ └┘ └┘
par └────┘ └┘ └┘
pid ┴┴ └┘ ┴┴
st ─────────────────────────┘└─
2537 end,
st ──┘
2538 this _ rfl
id └──┘ └─┘
src └─┘
typ └──┘ └─┘
2539
2540 @[simp] theorem disjoint_ndinsert_left {a : α} {s t : multiset α} :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2541 disjoint (ndinsert a s) t ↔ a ∉ t ∧ disjoint s t :=
id └──────┘ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘ ┴ ┴ ┴ └──────┘
typ └──────┘ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2542 iff.trans (by simp [disjoint]) disjoint_cons_left
id └───────┘ └──────┘ └────────────────┘
src └───────┘ └────┘└──────┘┴ └────────────────┘
typ └───────┘ └────┘└──────┘┴ └────────────────┘
doc └────┘└──────┘┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └──────────────┘
2543
2544 @[simp] theorem disjoint_ndinsert_right {a : α} {s t : multiset α} :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2545 disjoint s (ndinsert a t) ↔ a ∉ s ∧ disjoint s t :=
id └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘ ┴ ┴ ┴ └──────┘
typ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2546 disjoint_comm.trans $ by simp
id └───────────┘└────┘
src └───────────┘└────┘ └────
typ └───────────┘└────┘ └────
doc └────
txt └────
par └────
pid └
st └─────
2547
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
2548 /- finset union -/
src ───────────────────
typ ───────────────────
doc ───────────────────
txt ───────────────────
par ───────────────────
pid ───────────────────
st ───────────────────
2549
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2550 /-- `ndunion s t` is the lift of the list `union` operation. This operation
2551 does not respect multiplicities, unlike `s ∪ t`, but it is suitable as
2552 a union operation on `finset`. (`s ∪ t` would also work as a union operation
2553 on finset, but this is more efficient.) -/
2554 def ndunion (s t : multiset α) : multiset α :=
id └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ ┴
doc └──────┘ └──────┘
2555 quotient.lift_on₂ s t (λ l₁ l₂, (l₁.union l₂ : multiset α)) $ λ v₁ v₂ w₁ w₂ p₁ p₂,
id └───────────────┘ ┴ ┴ └┘ └┘ └┘└────┘ └┘ └──────┘ ┴ └┘ └┘ └┘ └┘ └┘ └┘
src └───────────────┘ └────┘ └──────┘
typ └───────────────┘ ┴ ┴ └┘ └┘ └┘└────┘ └┘ └──────┘ ┴ └┘ └┘ └┘ └┘ └┘ └┘
doc └──────┘
2556 quot.sound $ perm_union p₁ p₂
id └────────┘ └────────┘ └┘ └┘
src └────────┘ └────────┘
typ └────────┘ └────────┘ └┘ └┘
2557
2558 @[simp] theorem coe_ndunion (l₁ l₂ : list α) : @ndunion α _ l₁ l₂ = (l₁ ∪ l₂ : list α) := rfl
id └──┘ ┴ └─────┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ └──┘ ┴ └─┘
src └──┘ └─────┘ ┴ ┴ └──┘ └─┘
typ └──┘ ┴ └─────┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ └──┘ ┴ └─┘
doc └──┘ └─────┘
2559
2560 @[simp] theorem zero_ndunion (s : multiset α) : ndunion 0 s = s :=
id └──────┘ ┴ └─────┘ ┴ ┴ ┴
src └──────┘ └─────┘ ┴
typ └──────┘ ┴ └─────┘ ┴ ┴ ┴
doc └──┘ └──────┘ └─────┘
2561 quot.induction_on s $ λ l, rfl
id └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ └───────────────┘ ┴ ┴ └─┘
2562
2563 @[simp] theorem cons_ndunion (s t : multiset α) (a : α) : ndunion (a :: s) t = ndinsert a (ndunion s t) :=
id └──────┘ ┴ ┴ └─────┘ ┴ └┘ ┴ ┴ ┴ └──────┘ ┴ └─────┘ ┴ ┴
src └──────┘ └─────┘ └┘ ┴ └──────┘ └─────┘
typ └──────┘ ┴ ┴ └─────┘ ┴ └┘ ┴ ┴ ┴ └──────┘ ┴ └─────┘ ┴ ┴
doc └──┘ └──────┘ └─────┘ └┘ └──────┘ └─────┘
2564 quotient.induction_on₂ s t $ λ l₁ l₂, rfl
id └────────────────────┘ ┴ ┴ └┘ └┘ └─┘
src └────────────────────┘ └─┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └─┘
2565
2566 @[simp] theorem mem_ndunion {s t : multiset α} {a : α} : a ∈ ndunion s t ↔ a ∈ s ∨ a ∈ t :=
id └──────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └─────┘
2567 quotient.induction_on₂ s t $ λ l₁ l₂, list.mem_union
id └────────────────────┘ ┴ ┴ └┘ └┘ └────────────┘
src └────────────────────┘ └────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └────────────┘
2568
2569 theorem le_ndunion_right (s t : multiset α) : t ≤ ndunion s t :=
id └──────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
src └──────┘ ┴ └─────┘
typ └──────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
doc └──────┘ └─────┘
2570 quotient.induction_on₂ s t $ λ l₁ l₂,
id └────────────────────┘ ┴ ┴ └┘ └┘
src └────────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘
2571 subperm_of_sublist $ sublist_of_suffix $ suffix_union_right _ _
id └────────────────┘ └───────────────┘ └────────────────┘
src └────────────────┘ └───────────────┘ └────────────────┘
typ └────────────────┘ └───────────────┘ └────────────────┘
2572
2573 theorem ndunion_le_add (s t : multiset α) : ndunion s t ≤ s + t :=
id └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─────┘ ┴ ┴
typ └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └─────┘
2574 quotient.induction_on₂ s t $ λ l₁ l₂, subperm_of_sublist $ union_sublist_append _ _
id └────────────────────┘ ┴ ┴ └┘ └┘ └────────────────┘ └──────────────────┘
src └────────────────────┘ └────────────────┘ └──────────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └────────────────┘ └──────────────────┘
2575
2576 theorem ndunion_le {s t u : multiset α} : ndunion s t ≤ u ↔ s ⊆ u ∧ t ≤ u :=
id └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─────┘ ┴ ┴ ┴ ┴ ┴
typ └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └─────┘
2577 multiset.induction_on s (by simp) (by simp [ndinsert_le, and_comm, and.left_comm] {contextual := tt})
id └───────────────────┘ ┴ └─────────┘ └──────┘ └───────────┘ └┘
src └───────────────────┘ └──┘ └────┘└─────────┘└┘└──────┘└┘└───────────┘└┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └────┘└─────────┘└┘└──────┘└┘└───────────┘└┘ └────────────┘└┘┴
doc └──┘ └────┘ └┘ └┘ └┘ └────────────┘ ┴
txt └──┘ └────┘ └┘ └┘ └┘ └────────────┘ ┴
par └──┘ └────┘ └┘ └┘ └┘ └────────────┘ ┴
pid ┴┴ └┘ └┘ ┴┴ └────────────┘ ┴
st └───┘ └─────────────────────────────────────────────────────────────┘
2578
2579 theorem subset_ndunion_left (s t : multiset α) : s ⊆ ndunion s t :=
id └──────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
src └──────┘ ┴ └─────┘
typ └──────┘ ┴ ┴ ┴ └─────┘ ┴ ┴
doc └──────┘ └─────┘
2580 λ a h, mem_ndunion.2 $ or.inl h
id ┴ ┴ └─────────┘┴ └────┘ ┴
src └─────────┘┴ └────┘
typ ┴ ┴ └─────────┘┴ └────┘ ┴
2581
2582 theorem le_ndunion_left {s} (t : multiset α) (d : nodup s) : s ≤ ndunion s t :=
id └──────┘ ┴ └───┘ ┴ ┴ ┴ └─────┘ ┴ ┴
src └──────┘ └───┘ ┴ └─────┘
typ └──────┘ ┴ └───┘ ┴ ┴ ┴ └─────┘ ┴ ┴
doc └──────┘ └───┘ └─────┘
2583 (le_iff_subset d).2 $ subset_ndunion_left _ _
id └───────────┘ ┴ ┴ └─────────────────┘
src └───────────┘ ┴ └─────────────────┘
typ └───────────┘ ┴ ┴ └─────────────────┘
2584
2585 theorem ndunion_le_union (s t : multiset α) : ndunion s t ≤ s ∪ t :=
id └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─────┘ ┴ ┴
typ └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └─────┘
2586 ndunion_le.2 ⟨subset_of_le (le_union_left _ _), le_union_right _ _⟩
id └────────┘┴ └──────────┘ └───────────┘ └────────────┘
src └────────┘┴ └──────────┘ └───────────┘ └────────────┘
typ └────────┘┴ └──────────┘ └───────────┘ └────────────┘
2587
2588 theorem nodup_ndunion (s : multiset α) {t : multiset α} : nodup t → nodup (ndunion s t) :=
id └──────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ └─────┘ ┴ ┴
src └──────┘ └──────┘ └───┘ └───┘ └─────┘
typ └──────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ └─────┘ ┴ ┴
doc └──────┘ └──────┘ └───┘ └───┘ └─────┘
2589 quotient.induction_on₂ s t $ λ l₁ l₂, list.nodup_union _
id └────────────────────┘ ┴ ┴ └┘ └┘ └──────────────┘
src └────────────────────┘ └──────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └──────────────┘
2590
2591 @[simp] theorem ndunion_eq_union {s t : multiset α} (d : nodup s) : ndunion s t = s ∪ t :=
id └──────┘ ┴ └───┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───┘ └─────┘ ┴ ┴
typ └──────┘ ┴ └───┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └───┘ └─────┘
2592 le_antisymm (ndunion_le_union _ _) $ union_le (le_ndunion_left _ d) (le_ndunion_right _ _)
id └─────────┘ └──────────────┘ └──────┘ └─────────────┘ ┴ └──────────────┘
src └─────────┘ └──────────────┘ └──────┘ └─────────────┘ └──────────────┘
typ └─────────┘ └──────────────┘ └──────┘ └─────────────┘ ┴ └──────────────┘
2593
2594 theorem erase_dup_add (s t : multiset α) : erase_dup (s + t) = ndunion s (erase_dup t) :=
id └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ └───────┘ ┴
src └──────┘ └───────┘ ┴ ┴ └─────┘ └───────┘
typ └──────┘ ┴ └───────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ └───────┘ ┴
doc └──────┘ └───────┘ └─────┘ └───────┘
2595 quotient.induction_on₂ s t $ λ l₁ l₂, congr_arg coe $ erase_dup_append _ _
id └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └──────────────┘
src └────────────────────┘ └───────┘ └─┘ └──────────────┘
typ └────────────────────┘ ┴ ┴ └┘ └┘ └───────┘ └─┘ └──────────────┘
2596
2597 /- finset inter -/
2598
2599 /-- `ndinter s t` is the lift of the list `∩` operation. This operation
2600 does not respect multiplicities, unlike `s ∩ t`, but it is suitable as
2601 an intersection operation on `finset`. (`s ∩ t` would also work as a union operation
2602 on finset, but this is more efficient.) -/
2603 def ndinter (s t : multiset α) : multiset α := filter (∈ t) s
id └──────┘ ┴ └──────┘ ┴ └────┘ ┴ ┴ ┴
src └──────┘ └──────┘ └────┘ ┴
typ └──────┘ ┴ └──────┘ ┴ └────┘ ┴ ┴ ┴
doc └──────┘ └──────┘ └────┘
2604
2605 @[simp] theorem coe_ndinter (l₁ l₂ : list α) : @ndinter α _ l₁ l₂ = (l₁ ∩ l₂ : list α) := rfl
id └──┘ ┴ └─────┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ └──┘ ┴ └─┘
src └──┘ └─────┘ ┴ ┴ └──┘ └─┘
typ └──┘ ┴ └─────┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ └──┘ ┴ └─┘
doc └──┘ └─────┘
2606
2607 @[simp] theorem zero_ndinter (s : multiset α) : ndinter 0 s = 0 := rfl
id └──────┘ ┴ └─────┘ ┴ ┴ └─┘
src └──────┘ └─────┘ ┴ └─┘
typ └──────┘ ┴ └─────┘ ┴ ┴ └─┘
doc └──┘ └──────┘ └─────┘
2608
2609 @[simp] theorem cons_ndinter_of_mem {a : α} (s : multiset α) {t : multiset α} (h : a ∈ t) :
id ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ ┴
typ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──────┘
2610 ndinter (a::s) t = a :: (ndinter s t) := by simp [ndinter, h]
id └─────┘ ┴└┘┴ ┴ ┴ ┴ └┘ └─────┘ ┴ ┴ └─────┘ ┴
src └─────┘ └┘ ┴ └┘ └─────┘ └────┘└─────┘└┘ └─
typ └─────┘ ┴└┘┴ ┴ ┴ ┴ └┘ └─────┘ ┴ ┴ └────┘└─────┘└┘┴└─
doc └─────┘ └┘ └┘ └─────┘ └────┘└─────┘└┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └──────────────────
2611
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2612 @[simp] theorem ndinter_cons_of_not_mem {a : α} (s : multiset α) {t : multiset α} (h : a ∉ t) :
id ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ ┴
typ ┴ └──────┘ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──────┘
2613 ndinter (a::s) t = ndinter s t := by simp [ndinter, h]
id └─────┘ ┴└┘┴ ┴ ┴ └─────┘ ┴ ┴ └─────┘ ┴
src └─────┘ └┘ ┴ └─────┘ └────┘└─────┘└┘ └─
typ └─────┘ ┴└┘┴ ┴ ┴ └─────┘ ┴ ┴ └────┘└─────┘└┘┴└─
doc └─────┘ └┘ └─────┘ └────┘└─────┘└┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid ┴┴ └┘ ┴└
st └──────────────────
2614
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2615 @[simp] theorem mem_ndinter {s t : multiset α} {a : α} : a ∈ ndinter s t ↔ a ∈ s ∧ a ∈ t :=
id └──────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └─────┘
2616 mem_filter
id └────────┘
src └────────┘
typ └────────┘
2617
2618 theorem nodup_ndinter {s : multiset α} (t : multiset α) : nodup s → nodup (ndinter s t) :=
id └──────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ └─────┘ ┴ ┴
src └──────┘ └──────┘ └───┘ └───┘ └─────┘
typ └──────┘ ┴ └──────┘ ┴ └───┘ ┴ └───┘ └─────┘ ┴ ┴
doc └──────┘ └──────┘ └───┘ └───┘ └─────┘
2619 nodup_filter _
id └──────────┘
src └──────────┘
typ └──────────┘
2620
2621 theorem le_ndinter {s t u : multiset α} : s ≤ ndinter t u ↔ s ≤ t ∧ s ⊆ u :=
id └──────┘ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └─────┘
2622 by simp [ndinter, le_filter, subset_iff]
id └─────┘ └───────┘ └────────┘
src └────┘└─────┘└┘└───────┘└┘└────────┘└─
typ └────┘└─────┘└┘└───────┘└┘└────────┘└─
doc └────┘└─────┘└┘ └┘ └─
txt └────┘ └┘ └┘ └─
par └────┘ └┘ └┘ └─
pid ┴┴ └┘ └┘ ┴└
st └──────────────────────────────────────
2623
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2624 theorem ndinter_le_left (s t : multiset α) : ndinter s t ≤ s :=
id └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴
src └──────┘ └─────┘ ┴
typ └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴
doc └──────┘ └─────┘
2625 (le_ndinter.1 (le_refl _)).1
id └────────┘┴ └─────┘ ┴
src └────────┘┴ └─────┘ ┴
typ └────────┘┴ └─────┘ ┴
2626
2627 theorem ndinter_subset_right (s t : multiset α) : ndinter s t ⊆ t :=
id └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴
src └──────┘ └─────┘ ┴
typ └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴
doc └──────┘ └─────┘
2628 (le_ndinter.1 (le_refl _)).2
id └────────┘┴ └─────┘ ┴
src └────────┘┴ └─────┘ ┴
typ └────────┘┴ └─────┘ ┴
2629
2630 theorem ndinter_le_right {s} (t : multiset α) (d : nodup s) : ndinter s t ≤ t :=
id └──────┘ ┴ └───┘ ┴ └─────┘ ┴ ┴ ┴ ┴
src └──────┘ └───┘ └─────┘ ┴
typ └──────┘ ┴ └───┘ ┴ └─────┘ ┴ ┴ ┴ ┴
doc └──────┘ └───┘ └─────┘
2631 (le_iff_subset $ nodup_ndinter _ d).2 (ndinter_subset_right _ _)
id └───────────┘ └───────────┘ ┴ ┴ └──────────────────┘
src └───────────┘ └───────────┘ ┴ └──────────────────┘
typ └───────────┘ └───────────┘ ┴ ┴ └──────────────────┘
2632
2633 theorem inter_le_ndinter (s t : multiset α) : s ∩ t ≤ ndinter s t :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴
src └──────┘ ┴ ┴ └─────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ ┴
doc └──────┘ └─────┘
2634 le_ndinter.2 ⟨inter_le_left _ _, subset_of_le $ inter_le_right _ _⟩
id └────────┘┴ └───────────┘ └──────────┘ └────────────┘
src └────────┘┴ └───────────┘ └──────────┘ └────────────┘
typ └────────┘┴ └───────────┘ └──────────┘ └────────────┘
2635
2636 @[simp] theorem ndinter_eq_inter {s t : multiset α} (d : nodup s) : ndinter s t = s ∩ t :=
id └──────┘ ┴ └───┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └───┘ └─────┘ ┴ ┴
typ └──────┘ ┴ └───┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └───┘ └─────┘
2637 le_antisymm (le_inter (ndinter_le_left _ _) (ndinter_le_right _ d)) (inter_le_ndinter _ _)
id └─────────┘ └──────┘ └─────────────┘ └──────────────┘ ┴ └──────────────┘
src └─────────┘ └──────┘ └─────────────┘ └──────────────┘ └──────────────┘
typ └─────────┘ └──────┘ └─────────────┘ └──────────────┘ ┴ └──────────────┘
2638
2639 theorem ndinter_eq_zero_iff_disjoint {s t : multiset α} : ndinter s t = 0 ↔ disjoint s t :=
id └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └─────┘ ┴ ┴ └──────┘
typ └──────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └─────┘ └──────┘
2640 by rw ← subset_zero; simp [subset_iff, disjoint]
id └─────────┘ └────────┘ └──────┘
src └───┘└─────────┘ └────┘└────────┘└┘└──────┘└─
typ └───┘└─────────┘ └────┘└────────┘└┘└──────┘└─
doc └───┘ └────┘ └┘└──────┘└─
txt └───┘ └────┘ └┘ └─
par └───┘ └────┘ └┘ └─
pid └─┘ ┴┴ └┘ ┴└
st └──────────────────────────────────────────────
2641
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2642 end
2643
2644 /- fold -/
2645 section fold
2646 variables (op : α → α → α) [hc : is_commutative α op] [ha : is_associative α op]
id └────────────┘ └────────────┘
src └────────────┘ └────────────┘
typ └────────────┘ └────────────┘
2647 local notation a * b := op a b
2648 include hc ha
2649
2650 /-- `fold op b s` folds a commutative associative operation `op` over
2651 the multiset `s`. -/
2652 def fold : α → multiset α → α := foldr op (left_comm _ hc.comm ha.assoc)
id ┴ └──────┘ ┴ ┴ └───┘ └┘ └───────┘ └┘└───┘ └┘└────┘
src └──────┘ └───┘ └───────┘ └───┘ └────┘
typ ┴ └──────┘ ┴ ┴ └───┘ └┘ └───────┘ └┘└───┘ └┘└────┘
doc └──────┘ └───┘
2653
2654 theorem fold_eq_foldr (b : α) (s : multiset α) : fold op b s = foldr op (left_comm _ hc.comm ha.assoc) b s := rfl
id ┴ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ └───┘ └┘ └───────┘ └┘└───┘ └┘└────┘ ┴ ┴ └─┘
src └──────┘ └──┘ ┴ └───┘ └───────┘ └───┘ └────┘ └─┘
typ ┴ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ └───┘ └┘ └───────┘ └┘└───┘ └┘└────┘ ┴ ┴ └─┘
doc └──────┘ └──┘ └───┘
2655
2656 @[simp] theorem coe_fold_r (b : α) (l : list α) : fold op b l = l.foldr op b := rfl
id ┴ └──┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴└────┘ └┘ ┴ └─┘
src └──┘ └──┘ ┴ └────┘ └─┘
typ ┴ └──┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴└────┘ └┘ ┴ └─┘
doc └──┘ └──┘
2657
2658 theorem coe_fold_l (b : α) (l : list α) : fold op b l = l.foldl op b :=
id ┴ └──┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴└────┘ └┘ ┴
src └──┘ └──┘ ┴ └────┘
typ ┴ └──┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴└────┘ └┘ ┴
doc └──┘
2659 (coe_foldr_swap op _ b l).trans $ by simp [hc.comm]
id └────────────┘ └┘ ┴ ┴ └───┘
src └────────────┘ └───┘ └────┘ └─
typ └────────────┘ └┘ ┴ ┴ └───┘ └────┘└─────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └───────────────
2660
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2661 theorem fold_eq_foldl (b : α) (s : multiset α) : fold op b s = foldl op (right_comm _ hc.comm ha.assoc) b s :=
id ┴ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ └───┘ └┘ └────────┘ └┘└───┘ └┘└────┘ ┴ ┴
src └──────┘ └──┘ ┴ └───┘ └────────┘ └───┘ └────┘
typ ┴ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ └───┘ └┘ └────────┘ └┘└───┘ └┘└────┘ ┴ ┴
doc └──────┘ └──┘ └───┘
2662 quot.induction_on s $ λ l, coe_fold_l _ _ _
id └───────────────┘ ┴ ┴ └────────┘
src └───────────────┘ └────────┘
typ └───────────────┘ ┴ ┴ └────────┘
2663
2664 @[simp] theorem fold_zero (b : α) : (0 : multiset α).fold op b = b := rfl
id ┴ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ └─┘
src └──────┘ └──┘ ┴ └─┘
typ ┴ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ └─┘
doc └──┘ └──────┘ └──┘
2665
2666 @[simp] theorem fold_cons_left : ∀ (b a : α) (s : multiset α),
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2667 (a :: s).fold op b = a * s.fold op b := foldr_cons _ _
id ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴ ┴└───┘ └┘ ┴ └────────┘
src └┘ └──┘ ┴ └───┘ └────────┘
typ ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴ ┴└───┘ └┘ ┴ └────────┘
doc └┘ └──┘ └───┘
2668
2669 theorem fold_cons_right (b a : α) (s : multiset α) : (a :: s).fold op b = s.fold op b * a :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴ ┴ ┴
src └──────┘ └┘ └──┘ ┴ └───┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴ ┴ ┴
doc └──────┘ └┘ └──┘ └───┘
2670 by simp [hc.comm]
src └────┘ └─
typ └────┘└─────┘└─
doc └────┘ └─
txt └────┘ └─
par └────┘ └─
pid ┴┴ ┴└
st └───────────────
2671
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2672 theorem fold_cons'_right (b a : α) (s : multiset α) : (a :: s).fold op b = s.fold op (b * a) :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴ ┴ ┴
src └──────┘ └┘ └──┘ ┴ └───┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴ ┴ ┴
doc └──────┘ └┘ └──┘ └───┘
2673 by rw [fold_eq_foldl, foldl_cons, ← fold_eq_foldl]
id └───────────┘ └────────┘ └───────────┘
src └──┘└───────────┘└┘└────────┘└──┘└───────────┘└─
typ └──┘└───────────┘└┘└────────┘└──┘└───────────┘└─
doc └──┘ └┘ └──┘ └─
txt └──┘ └┘ └──┘ └─
par └──┘ └┘ └──┘ └─
pid └┘ └┘ └──┘ ┴└
st └────────────────┘└──────────┘└───────────────┘┴└
2674
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2675 theorem fold_cons'_left (b a : α) (s : multiset α) : (a :: s).fold op b = s.fold op (a * b) :=
id ┴ └──────┘ ┴ ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴ ┴ ┴
src └──────┘ └┘ └──┘ ┴ └───┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴ ┴ ┴
doc └──────┘ └┘ └──┘ └───┘
2676 by rw [fold_cons'_right, hc.comm]
id └──────────────┘
src └──┘└──────────────┘└┘ └─
typ └──┘└──────────────┘└┘└─────┘└─
doc └──┘ └┘ └─
txt └──┘ └┘ └─
par └──┘ └┘ └─
pid └┘ └┘ ┴└
st └───────────────────┘└───────┘┴└
2677
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2678 theorem fold_add (b₁ b₂ : α) (s₁ s₂ : multiset α) : (s₁ + s₂).fold op (b₁ * b₂) = s₁.fold op b₁ * s₂.fold op b₂ :=
id ┴ └──────┘ ┴ └┘ ┴ └┘ └──┘ └┘ └┘ ┴ └┘ ┴ └┘└───┘ └┘ └┘ ┴ └┘└───┘ └┘ └┘
src └──────┘ ┴ └──┘ ┴ └───┘ └───┘
typ ┴ └──────┘ ┴ └┘ ┴ └┘ └──┘ └┘ └┘ ┴ └┘ ┴ └┘└───┘ └┘ └┘ ┴ └┘└───┘ └┘ └┘
doc └──────┘ └──┘ └───┘ └───┘
2679 multiset.induction_on s₂
id └───────────────────┘ └┘
src └───────────────────┘
typ └───────────────────┘ └┘
2680 (by rw [add_zero, fold_zero, ← fold_cons'_right, ← fold_cons_right op])
id └──────┘ └───────┘ └──────────────┘ └─────────────┘ └┘
src └──┘└──────┘└┘└───────┘└──┘└──────────────┘└──┘└─────────────┘┴ ┴
typ └──┘└──────┘└┘└───────┘└──┘└──────────────┘└──┘└─────────────┘┴└┘┴
doc └──┘ └┘ └──┘ └──┘ ┴ ┴
txt └──┘ └┘ └──┘ └──┘ ┴ ┴
par └──┘ └┘ └──┘ └──┘ ┴ ┴
pid └┘ └┘ └──┘ └──┘ ┴ ┴
st └───────────┘└─────────┘└──────────────────┘└────────────────────┘┴
2681 (by simp {contextual := tt}; cc)
id └┘
src └───┘ └────────────┘└┘┴ └┘
typ └───┘ └────────────┘└┘┴ └┘
doc └───┘ └────────────┘ ┴ └┘
txt └───┘ └────────────┘ ┴ └┘
par └───┘ └────────────┘ ┴ └┘
pid ┴ └────────────┘ ┴
st └──────────────────────────┘
2682
2683 theorem fold_singleton (b a : α) : (a::0 : multiset α).fold op b = a * b := by simp
id ┴ ┴└┘ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴ ┴
src └┘ └──────┘ └──┘ ┴ └────
typ ┴ ┴└┘ └──────┘ ┴ └──┘ └┘ ┴ ┴ ┴ ┴ ┴ └────
doc └┘ └──────┘ └──┘ └────
txt └────
par └────
pid └
st └─────
2684
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2685 theorem fold_distrib {f g : β → α} (u₁ u₂ : α) (s : multiset β) :
id ┴ ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
2686 (s.map (λx, f x * g x)).fold op (u₁ * u₂) = (s.map f).fold op u₁ * (s.map g).fold op u₂ :=
id ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ └┘ └┘ ┴ └┘ ┴ ┴└──┘ ┴ └──┘ └┘ └┘ ┴ ┴└──┘ ┴ └──┘ └┘ └┘
src └──┘ └──┘ ┴ └──┘ └──┘ └──┘ └──┘
typ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ └┘ └┘ ┴ └┘ ┴ ┴└──┘ ┴ └──┘ └┘ └┘ ┴ ┴└──┘ ┴ └──┘ └┘ └┘
doc └──┘ └──┘ └──┘ └──┘ └──┘ └──┘
2687 multiset.induction_on s (by simp) (by simp {contextual := tt}; cc)
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴ └┘
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴ └┘
doc └──┘ └───┘ └────────────┘ ┴ └┘
txt └──┘ └───┘ └────────────┘ ┴ └┘
par └──┘ └───┘ └────────────┘ ┴ └┘
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────────┘
2688
2689 theorem fold_hom {op' : β → β → β} [is_commutative β op'] [is_associative β op']
id ┴ ┴ ┴ └────────────┘ ┴ └─┘ └────────────┘ ┴ └─┘
src └────────────┘ └────────────┘
typ ┴ ┴ ┴ └────────────┘ ┴ └─┘ └────────────┘ ┴ └─┘
2690 {m : α → β} (hm : ∀x y, m (op x y) = op' (m x) (m y)) (b : α) (s : multiset α) :
id ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
src ┴ └──────┘
typ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
2691 (s.map m).fold op' (m b) = m (s.fold op b) :=
id ┴└──┘ ┴ └──┘ └─┘ ┴ ┴ ┴ ┴ ┴└───┘ └┘ ┴
src └──┘ └──┘ ┴ └───┘
typ ┴└──┘ ┴ └──┘ └─┘ ┴ ┴ ┴ ┴ ┴└───┘ └┘ ┴
doc └──┘ └──┘ └───┘
2692 multiset.induction_on s (by simp) (by simp [hm] {contextual := tt})
id └───────────────────┘ ┴ └┘ └┘
src └───────────────────┘ └──┘ └────┘ └┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └────┘└┘└┘ └────────────┘└┘┴
doc └──┘ └────┘ └┘ └────────────┘ ┴
txt └──┘ └────┘ └┘ └────────────┘ ┴
par └──┘ └────┘ └┘ └────────────┘ ┴
pid ┴┴ ┴┴ └────────────┘ ┴
st └───┘ └───────────────────────────┘
2693
2694 theorem fold_union_inter [decidable_eq α] (s₁ s₂ : multiset α) (b₁ b₂ : α) :
id └──────────┘ ┴ └──────┘ ┴ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ └──────┘ ┴ ┴
doc └──────┘
2695 (s₁ ∪ s₂).fold op b₁ * (s₁ ∩ s₂).fold op b₂ = s₁.fold op b₁ * s₂.fold op b₂ :=
id └┘ ┴ └┘ └──┘ └┘ └┘ ┴ └┘ ┴ └┘ └──┘ └┘ └┘ ┴ └┘└───┘ └┘ └┘ ┴ └┘└───┘ └┘ └┘
src ┴ └──┘ ┴ └──┘ ┴ └───┘ └───┘
typ └┘ ┴ └┘ └──┘ └┘ └┘ ┴ └┘ ┴ └┘ └──┘ └┘ └┘ ┴ └┘└───┘ └┘ └┘ ┴ └┘└───┘ └┘ └┘
doc └──┘ └──┘ └───┘ └───┘
2696 by rw [← fold_add op, union_add_inter, fold_add op]
id └──────┘ └┘ └─────────────┘ └──────┘ └┘
src └────┘└──────┘┴ └┘└─────────────┘└┘└──────┘┴ └─
typ └────┘└──────┘┴└┘└┘└─────────────┘└┘└──────┘┴└┘└─
doc └────┘ ┴ └┘ └┘ ┴ └─
txt └────┘ ┴ └┘ └┘ ┴ └─
par └────┘ ┴ └┘ └┘ ┴ └─
pid └──┘ ┴ └┘ └┘ ┴ ┴└
st └────────────────┘└───────────────┘└───────────┘┴└
2697
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2698 @[simp] theorem fold_erase_dup_idem [decidable_eq α] [hi : is_idempotent α op] (s : multiset α) (b : α) :
id └──────────┘ ┴ └───────────┘ ┴ └┘ └──────┘ ┴ ┴
src └──────────┘ └───────────┘ └──────┘
typ └──────────┘ ┴ └───────────┘ ┴ └┘ └──────┘ ┴ ┴
doc └──┘ └──────┘
2699 (erase_dup s).fold op b = s.fold op b :=
id └───────┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴
src └───────┘ └──┘ ┴ └───┘
typ └───────┘ ┴ └──┘ └┘ ┴ ┴ ┴└───┘ └┘ ┴
doc └───────┘ └──┘ └───┘
2700 multiset.induction_on s (by simp) $ λ a s IH, begin
id └───────────────────┘ ┴ ┴ ┴ └┘
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘ ┴ ┴ └┘
doc └──┘
txt └──┘
par └──┘
st └───┘ └─────
2701 by_cases a ∈ s; simp [IH, h],
id ┴ ┴ ┴ └┘ ┴
src └───────┘ ┴┴┴ └────┘ └┘ ┴
typ └───────┘┴┴┴┴┴ └────┘└┘└┘┴┴
doc └───────┘ ┴ ┴ └────┘ └┘ ┴
txt └───────┘ ┴ ┴ └────┘ └┘ ┴
par └───────┘ ┴ ┴ └────┘ └┘ ┴
pid ┴ ┴ ┴ ┴┴ └┘ ┴
st ─────────────────────────────┘└─
2702 show fold op b s = op a (fold op b s),
id ┴ ┴ └──┘ └┘ ┴ ┴
src └───┘ ┴ ┴ ┴ ┴┴┴ ┴ ┴ └──┘┴ ┴ ┴ ┴
typ └───┘ ┴ ┴ ┴ ┴┴┴ ┴┴┴ └──┘┴└┘┴┴┴┴┴
doc └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘┴ ┴ ┴ ┴
txt └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
par └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
pid └───┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
st ─────────────────────────────────────────
2703 rw [← cons_erase h, fold_cons_left, ← ha.assoc, hi.idempotent],
id └────────┘ ┴ └────────────┘
src └────┘└────────┘┴ └┘└────────────┘└──┘ └┘ ┴
typ └────┘└────────┘┴┴└┘└────────────┘└──┘└──────┘└┘└───────────┘┴
doc └────┘ ┴ └┘ └──┘ └┘ ┴
txt └────┘ ┴ └┘ └──┘ └┘ ┴
par └────┘ ┴ └┘ └──┘ └┘ ┴
pid └──┘ ┴ └┘ └──┘ └┘ ┴
st ───────────────────┘└──────────────┘└──────────┘└─────────────┘└──
2704 end
st ──┘
2705
2706 end fold
2707
2708 theorem le_smul_erase_dup [decidable_eq α] (s : multiset α) :
id └──────────┘ ┴ └──────┘ ┴
src └──────────┘ └──────┘
typ └──────────┘ ┴ └──────┘ ┴
doc └──────┘
2709 ∃ n : ℕ, s ≤ n • erase_dup s :=
id ┴ ┴┴ ┴ ┴ ┴ ┴ └───────┘ ┴
src ┴ ┴┴ ┴ ┴ └───────┘
typ ┴ ┴┴ ┴ ┴ ┴ ┴ └───────┘ ┴
doc └───────┘
2710 ⟨(s.map (λ a, count a s)).fold max 0, le_iff_count.2 $ λ a, begin
id ┴└──┘ ┴ └───┘ ┴ ┴ └──┘ └─┘ └──────────┘┴ ┴
src └──┘ └───┘ └──┘ └─┘ └──────────┘┴
typ ┴└──┘ ┴ └───┘ ┴ ┴ └──┘ └─┘ └──────────┘┴ ┴
doc └──┘ └───┘ └──┘
st └─────
2711 rw count_smul, by_cases a ∈ s,
id └────────┘ ┴ ┴ ┴
src └─┘└────────┘ └───────┘ ┴┴┴
typ └─┘└────────┘ └───────┘┴┴┴┴┴
doc └─┘ └───────┘ ┴ ┴
txt └─┘ └───────┘ ┴ ┴
par └─┘ └───────┘ ┴ ┴
pid ┴ ┴ ┴ ┴
st ──────────────┘└──────────────┘└─
2712 { refine le_trans _ (mul_le_mul_left _ $ count_pos.2 $ mem_erase_dup.2 h),
id └──────┘ └─────────────┘ └───────┘ └───────────┘ ┴
src └─────┘└──────┘└─┘ └─────────────┘└─┘ ┴└───────┘└─┘ ┴└───────────┘└─┘ ┴
typ └─────┘└──────┘└─┘ └─────────────┘└─┘ ┴└───────┘└─┘ ┴└───────────┘└─┘┴┴
doc └─────┘ └─┘ └─┘ ┴ └─┘ ┴ └─┘ ┴
txt └─────┘ └─┘ └─┘ ┴ └─┘ ┴ └─┘ ┴
par └─────┘ └─┘ └─┘ ┴ └─┘ ┴ └─┘ ┴
pid ┴ └─┘ └─┘ ┴ └─┘ ┴ └─┘ ┴
st ───┘└─────────────────────────────────────────────────────────────────────┘└─
2713 have : count a s ≤ fold max 0 (map (λ a, count a s) (a :: erase s a));
id ┴ └──┘ └─┘ └─┘ └───┘ └┘ └───┘ ┴ ┴
src └─────┘ ┴ ┴ ┴┴┴└──┘┴└─┘└─┘ └─┘┴ └──┘└───┘┴ ┴ └┘ ┴└┘┴└───┘┴ ┴ └┘
typ └─────┘ ┴ ┴ ┴┴┴└──┘┴└─┘└─┘ └─┘┴ └──┘└───┘┴ ┴ └┘ ┴└┘┴└───┘┴┴┴┴└┘
doc └─────┘ ┴ ┴ ┴ ┴└──┘┴ └─┘ └─┘┴ └──┘└───┘┴ ┴ └┘ ┴└┘┴└───┘┴ ┴ └┘
txt └─────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ └──┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘
par └─────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ └──┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘
pid └───┘└┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ └──┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘
st ───────────────────────────────────────────────────────────────────────────
2714 [simp [le_max_left], simpa [cons_erase h]] },
id ┴ └─────────┘ └────────┘ ┴
src ┴└────┘└─────────┘┴ └─────┘└────────┘┴ ┴
typ ┴└────┘└─────────┘┴ └─────┘└────────┘┴┴┴
doc └────┘ ┴ └─────┘ ┴ ┴
txt └────┘ ┴ └─────┘ ┴ ┴
par └────┘ ┴ └─────┘ ┴ ┴
pid ┴┴ ┴ ┴┴ ┴ ┴
st ─────────────────────────────────────────────┘└─┘└
2715 { simp [count_eq_zero.2 h, nat.zero_le] }
id └───────────┘ ┴ └─────────┘
src └────┘└───────────┘└─┘ └┘└─────────┘└┘
typ └────┘└───────────┘└─┘┴└┘└─────────┘└┘
doc └────┘ └─┘ └┘ └┘
txt └────┘ └─┘ └┘ └┘
par └────┘ └─┘ └┘ └┘
pid ┴┴ └─┘ └┘ ┴┴
st ─────────────────────────────────────────┘└─
2716 end⟩
st ──┘
2717
2718 section sup
2719 variables [semilattice_sup_bot α]
id └─────────────────┘
src └─────────────────┘
typ └─────────────────┘
doc └─────────────────┘
2720
2721 /-- Supremum of a multiset: `sup {a, b, c} = a ⊔ b ⊔ c` -/
2722 def sup (s : multiset α) : α := s.fold (⊔) ⊥
id └──────┘ ┴ ┴ ┴└───┘ ┴ ┴
src └──────┘ └───┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴└───┘ ┴ ┴
doc └──────┘ └───┘
2723
2724 @[simp] lemma sup_zero : (0 : multiset α).sup = ⊥ :=
id └──────┘ ┴ └─┘ ┴ ┴
src └──────┘ └─┘ ┴ ┴
typ └──────┘ ┴ └─┘ ┴ ┴
doc └──┘ └──────┘ └─┘
2725 fold_zero _ _
id └───────┘
src └───────┘
typ └───────┘
2726
2727 @[simp] lemma sup_cons (a : α) (s : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2728 (a :: s).sup = a ⊔ s.sup :=
id ┴ └┘ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
src └┘ └─┘ ┴ ┴ └──┘
typ ┴ └┘ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
doc └┘ └─┘ └──┘
2729 fold_cons_left _ _ _ _
id └────────────┘
src └────────────┘
typ └────────────┘
2730
2731 @[simp] lemma sup_singleton {a : α} : (a::0).sup = a := by simp
id ┴ ┴└┘ └─┘ ┴ ┴
src └┘ └─┘ ┴ └────
typ ┴ ┴└┘ └─┘ ┴ ┴ └────
doc └──┘ └┘ └─┘ └────
txt └────
par └────
pid └
st └─────
2732
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2733 @[simp] lemma sup_add (s₁ s₂ : multiset α) : (s₁ + s₂).sup = s₁.sup ⊔ s₂.sup :=
id └──────┘ ┴ └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
src └──────┘ ┴ └─┘ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
doc └──┘ └──────┘ └─┘ └──┘ └──┘
2734 eq.trans (by simp [sup]) (fold_add _ _ _ _ _)
id └──────┘ └─┘ └──────┘
src └──────┘ └────┘└─┘┴ └──────┘
typ └──────┘ └────┘└─┘┴ └──────┘
doc └────┘└─┘┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └─────────┘
2735
2736 variables [decidable_eq α]
id └──────────┘
src └──────────┘
typ └──────────┘
2737
2738 @[simp] lemma sup_erase_dup (s : multiset α) : (erase_dup s).sup = s.sup :=
id └──────┘ ┴ └───────┘ ┴ └─┘ ┴ ┴└──┘
src └──────┘ └───────┘ └─┘ ┴ └──┘
typ └──────┘ ┴ └───────┘ ┴ └─┘ ┴ ┴└──┘
doc └──┘ └──────┘ └───────┘ └─┘ └──┘
2739 fold_erase_dup_idem _ _ _
id └─────────────────┘
src └─────────────────┘
typ └─────────────────┘
2740
2741 @[simp] lemma sup_ndunion (s₁ s₂ : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
2742 (ndunion s₁ s₂).sup = s₁.sup ⊔ s₂.sup :=
id └─────┘ └┘ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
src └─────┘ └─┘ ┴ └──┘ ┴ └──┘
typ └─────┘ └┘ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
doc └─────┘ └─┘ └──┘ └──┘
2743 by rw [← sup_erase_dup, erase_dup_ext.2, sup_erase_dup, sup_add]; simp
id └───────────┘ └───────────┘ └───────────┘ └─────┘
src └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
typ └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
doc └────┘ └┘ └──┘ └┘ ┴ └────
txt └────┘ └┘ └──┘ └┘ ┴ └────
par └────┘ └┘ └──┘ └┘ ┴ └────
pid └──┘ └┘ └──┘ └┘ ┴ └
st └──────────────────┘└─────────────┘└───────────────┘└───────┘┴└──────
2744
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2745 @[simp] lemma sup_union (s₁ s₂ : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
2746 (s₁ ∪ s₂).sup = s₁.sup ⊔ s₂.sup :=
id └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
src ┴ └─┘ ┴ └──┘ ┴ └──┘
typ └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
doc └─┘ └──┘ └──┘
2747 by rw [← sup_erase_dup, erase_dup_ext.2, sup_erase_dup, sup_add]; simp
id └───────────┘ └───────────┘ └───────────┘ └─────┘
src └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
typ └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
doc └────┘ └┘ └──┘ └┘ ┴ └────
txt └────┘ └┘ └──┘ └┘ ┴ └────
par └────┘ └┘ └──┘ └┘ ┴ └────
pid └──┘ └┘ └──┘ └┘ ┴ └
st └──────────────────┘└─────────────┘└───────────────┘└───────┘┴└──────
2748
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2749 @[simp] lemma sup_ndinsert (a : α) (s : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2750 (ndinsert a s).sup = a ⊔ s.sup :=
id └──────┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
src └──────┘ └─┘ ┴ ┴ └──┘
typ └──────┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
doc └──────┘ └─┘ └──┘
2751 by rw [← sup_erase_dup, erase_dup_ext.2, sup_erase_dup, sup_cons]; simp
id └───────────┘ └───────────┘ └───────────┘ └──────┘
src └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└──────┘┴ └────
typ └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└──────┘┴ └────
doc └────┘ └┘ └──┘ └┘ ┴ └────
txt └────┘ └┘ └──┘ └┘ ┴ └────
par └────┘ └┘ └──┘ └┘ ┴ └────
pid └──┘ └┘ └──┘ └┘ ┴ └
st └──────────────────┘└─────────────┘└───────────────┘└────────┘┴└──────
2752
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2753 lemma sup_le {s : multiset α} {a : α} : s.sup ≤ a ↔ (∀b ∈ s, b ≤ a) :=
id └──────┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ └──┘ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──┘
2754 multiset.induction_on s (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
2755 (by simp [or_imp_distrib, forall_and_distrib] {contextual := tt})
id └────────────┘ └────────────────┘ └┘
src └────┘└────────────┘└┘└────────────────┘└┘ └────────────┘└┘┴
typ └────┘└────────────┘└┘└────────────────┘└┘ └────────────┘└┘┴
doc └────┘ └┘ └┘ └────────────┘ ┴
txt └────┘ └┘ └┘ └────────────┘ ┴
par └────┘ └┘ └┘ └────────────┘ ┴
pid ┴┴ └┘ ┴┴ └────────────┘ ┴
st └───────────────────────────────────────────────────────────┘
2756
2757 lemma le_sup {s : multiset α} {a : α} (h : a ∈ s) : a ≤ s.sup :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└──┘
src └──────┘ ┴ ┴ └──┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└──┘
doc └──────┘ └──┘
2758 sup_le.1 (le_refl _) _ h
id └────┘┴ └─────┘ ┴
src └────┘┴ └─────┘
typ └────┘┴ └─────┘ ┴
2759
2760 lemma sup_mono {s₁ s₂ : multiset α} (h : s₁ ⊆ s₂) : s₁.sup ≤ s₂.sup :=
id └──────┘ ┴ └┘ ┴ └┘ └┘└──┘ ┴ └┘└──┘
src └──────┘ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ └┘ ┴ └┘ └┘└──┘ ┴ └┘└──┘
doc └──────┘ └──┘ └──┘
2761 sup_le.2 $ assume b hb, le_sup (h hb)
id └────┘┴ ┴ └┘ └────┘ ┴ └┘
src └────┘┴ └────┘
typ └────┘┴ ┴ └┘ └────┘ ┴ └┘
2762
2763 end sup
2764
2765 section inf
2766 variables [semilattice_inf_top α]
id └─────────────────┘
src └─────────────────┘
typ └─────────────────┘
doc └─────────────────┘
2767
2768 /-- Infimum of a multiset: `inf {a, b, c} = a ⊓ b ⊓ c` -/
2769 def inf (s : multiset α) : α := s.fold (⊓) ⊤
id └──────┘ ┴ ┴ ┴└───┘ ┴ ┴
src └──────┘ └───┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴└───┘ ┴ ┴
doc └──────┘ └───┘
2770
2771 @[simp] lemma inf_zero : (0 : multiset α).inf = ⊤ :=
id └──────┘ ┴ └─┘ ┴ ┴
src └──────┘ └─┘ ┴ ┴
typ └──────┘ ┴ └─┘ ┴ ┴
doc └──┘ └──────┘ └─┘
2772 fold_zero _ _
id └───────┘
src └───────┘
typ └───────┘
2773
2774 @[simp] lemma inf_cons (a : α) (s : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2775 (a :: s).inf = a ⊓ s.inf :=
id ┴ └┘ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
src └┘ └─┘ ┴ ┴ └──┘
typ ┴ └┘ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
doc └┘ └─┘ └──┘
2776 fold_cons_left _ _ _ _
id └────────────┘
src └────────────┘
typ └────────────┘
2777
2778 @[simp] lemma inf_singleton {a : α} : (a::0).inf = a := by simp
id ┴ ┴└┘ └─┘ ┴ ┴
src └┘ └─┘ ┴ └────
typ ┴ ┴└┘ └─┘ ┴ ┴ └────
doc └──┘ └┘ └─┘ └────
txt └────
par └────
pid └
st └─────
2779
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2780 @[simp] lemma inf_add (s₁ s₂ : multiset α) : (s₁ + s₂).inf = s₁.inf ⊓ s₂.inf :=
id └──────┘ ┴ └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
src └──────┘ ┴ └─┘ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
doc └──┘ └──────┘ └─┘ └──┘ └──┘
2781 eq.trans (by simp [inf]) (fold_add _ _ _ _ _)
id └──────┘ └─┘ └──────┘
src └──────┘ └────┘└─┘┴ └──────┘
typ └──────┘ └────┘└─┘┴ └──────┘
doc └────┘└─┘┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └─────────┘
2782
2783 variables [decidable_eq α]
id └──────────┘
src └──────────┘
typ └──────────┘
2784
2785 @[simp] lemma inf_erase_dup (s : multiset α) : (erase_dup s).inf = s.inf :=
id └──────┘ ┴ └───────┘ ┴ └─┘ ┴ ┴└──┘
src └──────┘ └───────┘ └─┘ ┴ └──┘
typ └──────┘ ┴ └───────┘ ┴ └─┘ ┴ ┴└──┘
doc └──┘ └──────┘ └───────┘ └─┘ └──┘
2786 fold_erase_dup_idem _ _ _
id └─────────────────┘
src └─────────────────┘
typ └─────────────────┘
2787
2788 @[simp] lemma inf_ndunion (s₁ s₂ : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
2789 (ndunion s₁ s₂).inf = s₁.inf ⊓ s₂.inf :=
id └─────┘ └┘ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
src └─────┘ └─┘ ┴ └──┘ ┴ └──┘
typ └─────┘ └┘ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
doc └─────┘ └─┘ └──┘ └──┘
2790 by rw [← inf_erase_dup, erase_dup_ext.2, inf_erase_dup, inf_add]; simp
id └───────────┘ └───────────┘ └───────────┘ └─────┘
src └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
typ └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
doc └────┘ └┘ └──┘ └┘ ┴ └────
txt └────┘ └┘ └──┘ └┘ ┴ └────
par └────┘ └┘ └──┘ └┘ ┴ └────
pid └──┘ └┘ └──┘ └┘ ┴ └
st └──────────────────┘└─────────────┘└───────────────┘└───────┘┴└──────
2791
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2792 @[simp] lemma inf_union (s₁ s₂ : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──┘ └──────┘
2793 (s₁ ∪ s₂).inf = s₁.inf ⊓ s₂.inf :=
id └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
src ┴ └─┘ ┴ └──┘ ┴ └──┘
typ └┘ ┴ └┘ └─┘ ┴ └┘└──┘ ┴ └┘└──┘
doc └─┘ └──┘ └──┘
2794 by rw [← inf_erase_dup, erase_dup_ext.2, inf_erase_dup, inf_add]; simp
id └───────────┘ └───────────┘ └───────────┘ └─────┘
src └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
typ └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└─────┘┴ └────
doc └────┘ └┘ └──┘ └┘ ┴ └────
txt └────┘ └┘ └──┘ └┘ ┴ └────
par └────┘ └┘ └──┘ └┘ ┴ └────
pid └──┘ └┘ └──┘ └┘ ┴ └
st └──────────────────┘└─────────────┘└───────────────┘└───────┘┴└──────
2795
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2796 @[simp] lemma inf_ndinsert (a : α) (s : multiset α) :
id ┴ └──────┘ ┴
src └──────┘
typ ┴ └──────┘ ┴
doc └──┘ └──────┘
2797 (ndinsert a s).inf = a ⊓ s.inf :=
id └──────┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
src └──────┘ └─┘ ┴ ┴ └──┘
typ └──────┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴└──┘
doc └──────┘ └─┘ └──┘
2798 by rw [← inf_erase_dup, erase_dup_ext.2, inf_erase_dup, inf_cons]; simp
id └───────────┘ └───────────┘ └───────────┘ └──────┘
src └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└──────┘┴ └────
typ └────┘└───────────┘└┘└───────────┘└──┘└───────────┘└┘└──────┘┴ └────
doc └────┘ └┘ └──┘ └┘ ┴ └────
txt └────┘ └┘ └──┘ └┘ ┴ └────
par └────┘ └┘ └──┘ └┘ ┴ └────
pid └──┘ └┘ └──┘ └┘ ┴ └
st └──────────────────┘└─────────────┘└───────────────┘└────────┘┴└──────
2799
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2800 lemma le_inf {s : multiset α} {a : α} : a ≤ s.inf ↔ (∀b ∈ s, a ≤ b) :=
id └──────┘ ┴ ┴ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──────┘ └──┘
2801 multiset.induction_on s (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
2802 (by simp [or_imp_distrib, forall_and_distrib] {contextual := tt})
id └────────────┘ └────────────────┘ └┘
src └────┘└────────────┘└┘└────────────────┘└┘ └────────────┘└┘┴
typ └────┘└────────────┘└┘└────────────────┘└┘ └────────────┘└┘┴
doc └────┘ └┘ └┘ └────────────┘ ┴
txt └────┘ └┘ └┘ └────────────┘ ┴
par └────┘ └┘ └┘ └────────────┘ ┴
pid ┴┴ └┘ ┴┴ └────────────┘ ┴
st └───────────────────────────────────────────────────────────┘
2803
2804 lemma inf_le {s : multiset α} {a : α} (h : a ∈ s) : s.inf ≤ a :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴└──┘ ┴ ┴
src └──────┘ ┴ └──┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴└──┘ ┴ ┴
doc └──────┘ └──┘
2805 le_inf.1 (le_refl _) _ h
id └────┘┴ └─────┘ ┴
src └────┘┴ └─────┘
typ └────┘┴ └─────┘ ┴
2806
2807 lemma inf_mono {s₁ s₂ : multiset α} (h : s₁ ⊆ s₂) : s₂.inf ≤ s₁.inf :=
id └──────┘ ┴ └┘ ┴ └┘ └┘└──┘ ┴ └┘└──┘
src └──────┘ ┴ └──┘ ┴ └──┘
typ └──────┘ ┴ └┘ ┴ └┘ └┘└──┘ ┴ └┘└──┘
doc └──────┘ └──┘ └──┘
2808 le_inf.2 $ assume b hb, inf_le (h hb)
id └────┘┴ ┴ └┘ └────┘ ┴ └┘
src └────┘┴ └────┘
typ └────┘┴ ┴ └┘ └────┘ ┴ └┘
2809
2810 end inf
2811
2812 section sort
2813 variables (r : α → α → Prop) [decidable_rel r]
id └───────────┘
src └───────────┘
typ └───────────┘
2814 [is_trans α r] [is_antisymm α r] [is_total α r]
id └──────┘ └─────────┘ └──────┘
src └──────┘ └─────────┘ └──────┘
typ └──────┘ └─────────┘ └──────┘
2815
2816 /-- `sort s` constructs a sorted list from the multiset `s`.
2817 (Uses merge sort algorithm.) -/
2818 def sort (s : multiset α) : list α :=
id └──────┘ ┴ └──┘ ┴
src └──────┘ └──┘
typ └──────┘ ┴ └──┘ ┴
doc └──────┘
2819 quot.lift_on s (merge_sort r) $ λ a b h,
id └──────────┘ ┴ └────────┘ ┴ ┴ ┴ ┴
src └──────────┘ └────────┘
typ └──────────┘ ┴ └────────┘ ┴ ┴ ┴ ┴
doc └────────┘
2820 eq_of_sorted_of_perm
id └──────────────────┘
src └──────────────────┘
typ └──────────────────┘
2821 ((perm_merge_sort _ _).trans $ h.trans (perm_merge_sort _ _).symm)
id └─────────────┘ └───┘ ┴└────┘ └─────────────┘ └──┘
src └─────────────┘ └───┘ └────┘ └─────────────┘ └──┘
typ └─────────────┘ └───┘ ┴└────┘ └─────────────┘ └──┘
2822 (sorted_merge_sort r _)
id └───────────────┘ ┴
src └───────────────┘
typ └───────────────┘ ┴
2823 (sorted_merge_sort r _)
id └───────────────┘ ┴
src └───────────────┘
typ └───────────────┘ ┴
2824
2825 @[simp] theorem coe_sort (l : list α) : sort r l = merge_sort r l := rfl
id └──┘ ┴ └──┘ ┴ ┴ ┴ └────────┘ ┴ ┴ └─┘
src └──┘ └──┘ ┴ └────────┘ └─┘
typ └──┘ ┴ └──┘ ┴ ┴ ┴ └────────┘ ┴ ┴ └─┘
doc └──┘ └──┘ └────────┘
2826
2827 @[simp] theorem sort_sorted (s : multiset α) : sorted r (sort r s) :=
id └──────┘ ┴ └────┘ ┴ └──┘ ┴ ┴
src └──────┘ └────┘ └──┘
typ └──────┘ ┴ └────┘ ┴ └──┘ ┴ ┴
doc └──┘ └──────┘ └────┘ └──┘
2828 quot.induction_on s $ λ l, sorted_merge_sort r _
id └───────────────┘ ┴ ┴ └───────────────┘ ┴
src └───────────────┘ └───────────────┘
typ └───────────────┘ ┴ ┴ └───────────────┘ ┴
2829
2830 @[simp] theorem sort_eq (s : multiset α) : ↑(sort r s) = s :=
id └──────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──┘ ┴
typ └──────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──┘
2831 quot.induction_on s $ λ l, quot.sound $ perm_merge_sort _ _
id └───────────────┘ ┴ ┴ └────────┘ └─────────────┘
src └───────────────┘ └────────┘ └─────────────┘
typ └───────────────┘ ┴ ┴ └────────┘ └─────────────┘
2832
2833 @[simp] theorem mem_sort {s : multiset α} {a : α} : a ∈ sort r s ↔ a ∈ s :=
id └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴
src └──────┘ ┴ └──┘ ┴ ┴
typ └──────┘ ┴ ┴ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────┘ └──┘
2834 by rw [← mem_coe, sort_eq]
id └─────┘ └─────┘
src └────┘└─────┘└┘└─────┘└─
typ └────┘└─────┘└┘└─────┘└─
doc └────┘ └┘ └─
txt └────┘ └┘ └─
par └────┘ └┘ └─
pid └──┘ └┘ ┴└
st └────────────┘└───────┘┴└
2835
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2836 @[simp] theorem length_sort {s : multiset α} : (sort r s).length = s.card :=
id └──────┘ ┴ └──┘ ┴ ┴ └────┘ ┴ ┴└───┘
src └──────┘ └──┘ └────┘ ┴ └───┘
typ └──────┘ ┴ └──┘ ┴ ┴ └────┘ ┴ ┴└───┘
doc └──┘ └──────┘ └──┘ └───┘
2837 quot.induction_on s $ length_merge_sort _
id └───────────────┘ ┴ └───────────────┘
src └───────────────┘ └───────────────┘
typ └───────────────┘ ┴ └───────────────┘
2838
2839 end sort
2840
2841 instance [has_repr α] : has_repr (multiset α) :=
id └──────┘ ┴ └──────┘ └──────┘ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ └──────┘ └──────┘ ┴
doc └──────┘
2842 ⟨λ s, "{" ++ string.intercalate ", " ((s.map repr).sort (≤)) ++ "}"⟩
id ┴ └┘ └────────────────┘ ┴└──┘ └──┘ └──┘ ┴ └┘
src └┘ └────────────────┘ └──┘ └──┘ └──┘ ┴ └┘
typ ┴ └┘ └────────────────┘ ┴└──┘ └──┘ └──┘ ┴ └┘
doc └──┘ └──┘
2843
2844 section sections
2845
2846 def sections (s : multiset (multiset α)) : multiset (multiset α) :=
id └──────┘ └──────┘ ┴ └──────┘ └──────┘ ┴
src └──────┘ └──────┘ └──────┘ └──────┘
typ └──────┘ └──────┘ ┴ └──────┘ └──────┘ ┴
doc └──────┘ └──────┘ └──────┘ └──────┘
2847 multiset.rec_on s {0} (λs _ c, s.bind $ λa, c.map ((::) a))
id └─────────────┘ ┴ ┴ ┴ ┴ ┴ ┴└───┘ ┴ ┴└──┘ └──┘ ┴
src └─────────────┘ ┴ └───┘ └──┘ └──┘
typ └─────────────┘ ┴ ┴ ┴ ┴ ┴ ┴└───┘ ┴ ┴└──┘ └──┘ ┴
doc └───┘ └──┘ └──┘
2848 (assume a₀ a₁ s pi, by simp [map_bind, bind_bind a₀ a₁, cons_swap])
id └┘ └┘ ┴ └┘ └──────┘ └───────┘ └┘ └┘ └───────┘
src └────┘└──────┘└┘└───────┘┴ ┴ └┘└───────┘┴
typ └┘ └┘ ┴ └┘ └────┘└──────┘└┘└───────┘┴└┘┴└┘└┘└───────┘┴
doc └────┘ └┘ ┴ ┴ └┘ ┴
txt └────┘ └┘ ┴ ┴ └┘ ┴
par └────┘ └┘ ┴ ┴ └┘ ┴
pid ┴┴ └┘ ┴ ┴ └┘ ┴
st └──────────────────────────────────────────┘
2849
2850 @[simp] lemma sections_zero : sections (0 : multiset (multiset α)) = 0::0 :=
id └──────┘ └──────┘ └──────┘ ┴ ┴ └┘
src └──────┘ └──────┘ └──────┘ ┴ └┘
typ └──────┘ └──────┘ └──────┘ ┴ ┴ └┘
doc └──┘ └──────┘ └──────┘ └┘
2851 rfl
id └─┘
src └─┘
typ └─┘
2852
2853 @[simp] lemma sections_cons (s : multiset (multiset α)) (m : multiset α) :
id └──────┘ └──────┘ ┴ └──────┘ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ └──────┘ ┴ └──────┘ ┴
doc └──┘ └──────┘ └──────┘ └──────┘
2854 sections (m :: s) = m.bind (λa, (sections s).map ((::) a)) :=
id └──────┘ ┴ └┘ ┴ ┴ ┴└───┘ ┴ └──────┘ ┴ └─┘ └──┘ ┴
src └──────┘ └┘ ┴ └───┘ └──────┘ └─┘ └──┘
typ └──────┘ ┴ └┘ ┴ ┴ ┴└───┘ ┴ └──────┘ ┴ └─┘ └──┘ ┴
doc └┘ └───┘ └─┘ └──┘
2855 rec_on_cons m s
id └─────────┘ ┴ ┴
src └─────────┘
typ └─────────┘ ┴ ┴
2856
2857 lemma coe_sections : ∀(l : list (list α)),
id ┴ └──┘ └──┘ ┴
src └──┘ └──┘
typ ┴ └──┘ └──┘ ┴
2858 sections ((l.map (λl:list α, (l : multiset α))) : multiset (multiset α)) =
id └──────┘ ┴└──┘ └──┘ ┴ ┴ └──────┘ ┴ └──────┘ └──────┘ ┴ ┴
src └──────┘ └──┘ └──┘ └──────┘ └──────┘ └──────┘ ┴
typ └──────┘ ┴└──┘ └──┘ ┴ ┴ └──────┘ ┴ └──────┘ └──────┘ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2859 ((l.sections.map (λl:list α, (l : multiset α))) : multiset (multiset α))
id ┴└───────┘└──┘ └──┘ ┴ ┴ └──────┘ ┴ └──────┘ └──────┘ ┴
src └───────┘└──┘ └──┘ └──────┘ └──────┘ └──────┘
typ ┴└───────┘└──┘ └──┘ ┴ ┴ └──────┘ ┴ └──────┘ └──────┘ ┴
doc └───────┘ └──────┘ └──────┘ └──────┘
2860 | [] := rfl
id └┘ └─┘
src └┘ └─┘
typ └┘ └─┘
2861 | (a :: l) :=
id └┘
src └┘
typ └┘
2862 begin
st └─────
2863 simp,
src └──┘
typ └──┘
doc └──┘
txt └──┘
par └──┘
st ───────┘└─
2864 rw [← cons_coe, sections_cons, bind_map_comm, coe_sections l],
id └──────┘ └───────────┘ └───────────┘ └──────────┘ ┴
src └────┘└──────┘└┘└───────────┘└┘└───────────┘└┘ ┴ ┴
typ └────┘└──────┘└┘└───────────┘└┘└───────────┘└┘└──────────┘┴┴┴
doc └────┘ └┘ └┘ └┘ ┴ ┴
txt └────┘ └┘ └┘ └┘ ┴ ┴
par └────┘ └┘ └┘ └┘ ┴ ┴
pid └──┘ └┘ └┘ └┘ ┴ ┴
st ─────────────────┘└─────────────┘└─────────────┘└──────────────┘└──
2865 simp [list.sections, (∘), list.bind]
id └───────────┘ ┴ └───────┘
src └────┘└───────────┘└┘┴└──┘└───────┘└─
typ └────┘└───────────┘└┘┴└──┘└───────┘└─
doc └────┘└───────────┘└┘ └──┘ └─
txt └────┘ └┘ └──┘ └─
par └────┘ └┘ └──┘ └─
pid ┴┴ └┘ └──┘ ┴└
st ─────────────────────────────────────────
2866 end
src ─┘
typ ─┘
doc ─┘
txt ─┘
par ─┘
pid ─┘
st ─┘└─┘
2867
2868 @[simp] lemma sections_add (s t : multiset (multiset α)) :
id └──────┘ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ └──────┘ ┴
doc └──┘ └──────┘ └──────┘
2869 sections (s + t) = (sections s).bind (λm, (sections t).map ((+) m)) :=
id └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ └──┘ ┴ └──────┘ ┴ └─┘ ┴ ┴
src └──────┘ ┴ ┴ └──────┘ └──┘ └──────┘ └─┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ └──────┘ ┴ └──┘ ┴ └──────┘ ┴ └─┘ ┴ ┴
doc └──┘ └─┘
2870 multiset.induction_on s (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
2871 (assume a s ih, by simp [ih, bind_assoc, map_bind, bind_map, -add_comm])
id ┴ ┴ └┘ └┘ └────────┘ └──────┘ └──────┘
src └────┘ └┘└────────┘└┘└──────┘└┘└──────┘└──────────┘
typ ┴ ┴ └┘ └────┘└┘└┘└────────┘└┘└──────┘└┘└──────┘└──────────┘
doc └────┘ └┘ └┘ └┘ └──────────┘
txt └────┘ └┘ └┘ └┘ └──────────┘
par └────┘ └┘ └┘ └┘ └──────────┘
pid ┴┴ └┘ └┘ └┘ └──────────┘
st └───────────────────────────────────────────────────┘
2872
2873 lemma mem_sections {s : multiset (multiset α)} :
id └──────┘ └──────┘ ┴
src └──────┘ └──────┘
typ └──────┘ └──────┘ ┴
doc └──────┘ └──────┘
2874 ∀{a}, a ∈ sections s ↔ s.rel (λs a, a ∈ s) a :=
id ┴ ┴ ┴ └──────┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └──────┘ ┴ └──┘ ┴
typ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴└──┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘
2875 multiset.induction_on s (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
2876 (assume a s ih a',
id ┴ ┴ └┘ └┘
typ ┴ ┴ └┘ └┘
2877 by simp [ih, rel_cons_left, -exists_and_distrib_left, exists_and_distrib_left.symm, eq_comm])
id └───────────┘ └─────┘
src └────┘ └┘└───────────┘└──────────────────────────┘ └┘└─────┘┴
typ └────┘└┘└┘└───────────┘└──────────────────────────┘└──────────────────────────┘└┘└─────┘┴
doc └────┘ └┘ └──────────────────────────┘ └┘ ┴
txt └────┘ └┘ └──────────────────────────┘ └┘ ┴
par └────┘ └┘ └──────────────────────────┘ └┘ ┴
pid ┴┴ └┘ └──────────────────────────┘ └┘ ┴
st └────────────────────────────────────────────────────────────────────────────────────────┘
2878
2879 lemma card_sections {s : multiset (multiset α)} : card (sections s) = prod (s.map card) :=
id └──────┘ └──────┘ ┴ └──┘ └──────┘ ┴ ┴ └──┘ ┴└──┘ └──┘
src └──────┘ └──────┘ └──┘ └──────┘ ┴ └──┘ └──┘ └──┘
typ └──────┘ └──────┘ ┴ └──┘ └──────┘ ┴ ┴ └──┘ ┴└──┘ └──┘
doc └──────┘ └──────┘ └──┘ └──┘ └──┘ └──┘
2880 multiset.induction_on s (by simp) (by simp {contextual := tt})
id └───────────────────┘ ┴ └┘
src └───────────────────┘ └──┘ └───┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └───┘ └────────────┘└┘┴
doc └──┘ └───┘ └────────────┘ ┴
txt └──┘ └───┘ └────────────┘ ┴
par └──┘ └───┘ └────────────┘ ┴
pid ┴ └────────────┘ ┴
st └───┘ └──────────────────────┘
2881
2882 lemma prod_map_sum [comm_semiring α] {s : multiset (multiset α)} :
id └───────────┘ ┴ └──────┘ └──────┘ ┴
src └───────────┘ └──────┘ └──────┘
typ └───────────┘ ┴ └──────┘ └──────┘ ┴
doc └──────┘ └──────┘
2883 prod (s.map sum) = sum ((sections s).map prod) :=
id └──┘ ┴└──┘ └─┘ ┴ └─┘ └──────┘ ┴ └─┘ └──┘
src └──┘ └──┘ └─┘ ┴ └─┘ └──────┘ └─┘ └──┘
typ └──┘ ┴└──┘ └─┘ ┴ └─┘ └──────┘ ┴ └─┘ └──┘
doc └──┘ └──┘ └─┘ └──┘
2884 multiset.induction_on s (by simp)
id └───────────────────┘ ┴
src └───────────────────┘ └──┘
typ └───────────────────┘ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
2885 (assume a s ih, by simp [ih, map_bind, sum_map_mul_left, sum_map_mul_right])
id ┴ ┴ └┘ └┘ └──────┘ └──────────────┘ └───────────────┘
src └────┘ └┘└──────┘└┘└──────────────┘└┘└───────────────┘┴
typ ┴ ┴ └┘ └────┘└┘└┘└──────┘└┘└──────────────┘└┘└───────────────┘┴
doc └────┘ └┘ └┘ └┘ ┴
txt └────┘ └┘ └┘ └┘ ┴
par └────┘ └┘ └┘ └┘ ┴
pid ┴┴ └┘ └┘ └┘ ┴
st └───────────────────────────────────────────────────────┘
2886
2887 end sections
2888
2889 section pi
2890 variables [decidable_eq α] {δ : α → Type*}
id └──────────┘
src └──────────┘
typ └──────────┘
2891 open function
2892
2893 def pi.cons (m : multiset α) (a : α) (b : δ a) (f : Πa∈m, δ a) : Πa'∈a::m, δ a' :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴└┘┴ ┴ └┘
src └──────┘ └┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴└┘┴ ┴ └┘
doc └──────┘ └┘
2894 λa' ha', if h : a' = a then eq.rec b h.symm else f a' $ (mem_cons.1 ha').resolve_left h
id └┘ └─┘ └┘ └┘ ┴ ┴ └────┘ ┴ ┴└───┘ ┴ └┘ ┴ └──────┘┴ └─┘ └──────────┘ ┴
src └┘ ┴ └────┘ └───┘ └──────┘┴ └──────────┘
typ └┘ └─┘ └┘ └┘ ┴ ┴ └────┘ ┴ ┴└───┘ ┴ └┘ ┴ └──────┘┴ └─┘ └──────────┘ ┴
2895
2896 def pi.empty (δ : α → Type*) : (Πa∈(0:multiset α), δ a) .
id ┴ ┴ └──────┘ ┴ ┴ ┴
src └──────┘
typ ┴ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘
2897
2898 lemma pi.cons_same {m : multiset α} {a : α} {b : δ a} {f : Πa∈m, δ a} (h : a ∈ a :: m) :
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
src └──────┘ ┴ └┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
doc └──────┘ └┘
2899 pi.cons m a b f a h = b :=
id └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └─────┘ ┴
typ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
2900 dif_pos rfl
id └─────┘ └─┘
src └─────┘ └─┘
typ └─────┘ └─┘
2901
2902 lemma pi.cons_ne {m : multiset α} {a a' : α} {b : δ a} {f : Πa∈m, δ a} (h' : a' ∈ a :: m) (h : a' ≠ a) :
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘ ┴ └┘ ┴ ┴
src └──────┘ ┴ └┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘ ┴ └┘ ┴ ┴
doc └──────┘ └┘
2903 pi.cons m a b f a' h' = f a' ((mem_cons.1 h').resolve_left h) :=
id └─────┘ ┴ ┴ ┴ ┴ └┘ └┘ ┴ ┴ └┘ └──────┘┴ └┘ └──────────┘ ┴
src └─────┘ ┴ └──────┘┴ └──────────┘
typ └─────┘ ┴ ┴ ┴ ┴ └┘ └┘ ┴ ┴ └┘ └──────┘┴ └┘ └──────────┘ ┴
2904 dif_neg h
id └─────┘ ┴
src └─────┘
typ └─────┘ ┴
2905
2906 lemma pi.cons_swap {a a' : α} {b : δ a} {b' : δ a'} {m : multiset α} {f : Πa∈m, δ a} (h : a ≠ a') :
id ┴ ┴ ┴ ┴ └┘ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
src └──────┘ ┴
typ ┴ ┴ ┴ ┴ └┘ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
doc └──────┘
2907 pi.cons (a' :: m) a b (pi.cons m a' b' f) == pi.cons (a :: m) a' b' (pi.cons m a b f) :=
id └─────┘ └┘ └┘ ┴ ┴ ┴ └─────┘ ┴ └┘ └┘ ┴ └┘ └─────┘ ┴ └┘ ┴ └┘ └┘ └─────┘ ┴ ┴ ┴ ┴
src └─────┘ └┘ └─────┘ └┘ └─────┘ └┘ └─────┘
typ └─────┘ └┘ └┘ ┴ ┴ ┴ └─────┘ ┴ └┘ └┘ ┴ └┘ └─────┘ ┴ └┘ ┴ └┘ └┘ └─────┘ ┴ ┴ ┴ ┴
doc └┘ └┘
2908 begin
st └─────
2909 apply hfunext, { refl }, intros a'' _ h, subst h,
id └─────┘ ┴
src └────┘└─────┘ └───┘ └────────────┘ └────┘
typ └────┘└─────┘ └───┘ └────────────┘ └────┘┴
doc └────┘ └───┘ └────────────┘ └────┘
txt └────┘ └───┘ └────────────┘ └────┘
par └────┘ └───┘ └────────────┘ └────┘
pid ┴ ┴ └──────┘ ┴
st ──────────────┘└──┘└───┘└┘└─────────────┘└───────┘└─
2910 apply hfunext, { rw [cons_swap] }, intros ha₁ ha₂ h,
id └─────┘ └───────┘
src └────┘└─────┘ └──┘└───────┘└┘ └──────────────┘
typ └────┘└─────┘ └──┘└───────┘└┘ └──────────────┘
doc └────┘ └──┘ └┘ └──────────────┘
txt └────┘ └──┘ └┘ └──────────────┘
par └────┘ └──┘ └┘ └──────────────┘
pid ┴ └┘ ┴┴ └────────┘
st ──────────────┘└──┘└───────────┘┴┴└┘└───────────────┘└─
2911 by_cases h₁ : a'' = a; by_cases h₂ : a'' = a';
id └─┘ ┴ ┴ └─┘ └┘
src └───────┘ └─┘ ┴┴┴ └───────┘ └─┘ ┴ ┴
typ └───────┘ └─┘└─┘┴┴┴┴ └───────┘ └─┘└─┘┴ ┴└┘
doc └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴
txt └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴
par └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
st ─────────────────────────────────────────────────
2912 simp [*, pi.cons_same, pi.cons_ne] at *,
id └──────────┘ └────────┘
src └───────┘└──────────┘└┘└────────┘└────┘
typ └───────┘└──────────┘└┘└────────┘└────┘
doc └───────┘ └┘ └────┘
txt └───────┘ └┘ └────┘
par └───────┘ └┘ └────┘
pid ┴└──┘ └┘ ┴┴└──┘
st ──────────────────────────────────────────┘└─
2913 { subst h₁, rw [pi.cons_same, pi.cons_same] },
id └┘ └──────────┘ └──────────┘
src └────┘ └──┘└──────────┘└┘└──────────┘└┘
typ └────┘└┘ └──┘└──────────┘└┘└──────────┘└┘
doc └────┘ └──┘ └┘ └┘
txt └────┘ └──┘ └┘ └┘
par └────┘ └──┘ └┘ └┘
pid ┴ └┘ └┘ ┴┴
st ───┘└──────┘└────────────────┘└────────────┘┴┴└┘└
2914 { subst h₂, rw [pi.cons_same, pi.cons_same] }
id └┘ └──────────┘ └──────────┘
src └────┘ └──┘└──────────┘└┘└──────────┘└┘
typ └────┘└┘ └──┘└──────────┘└┘└──────────┘└┘
doc └────┘ └──┘ └┘ └┘
txt └────┘ └──┘ └┘ └┘
par └────┘ └──┘ └┘ └┘
pid ┴ └┘ └┘ ┴┴
st ───────────┘└────────────────┘└────────────┘┴┴└─
2915 end
st ──┘
2916
2917 /-- `pi m t` constructs the Cartesian product over `t` indexed by `m`. -/
2918 def pi (m : multiset α) (t : Πa, multiset (δ a)) : multiset (Πa∈m, δ a) :=
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──────┘ └──────┘ └──────┘
2919 m.rec_on {pi.empty δ} (λa m (p : multiset (Πa∈m, δ a)), (t a).bind $ λb, p.map $ pi.cons m a b)
id ┴└─────┘ ┴└──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴└──┘ └─────┘ ┴ ┴ ┴
src └─────┘ ┴└──────┘ └──────┘ └──┘ └──┘ └─────┘
typ ┴└─────┘ ┴└──────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ ┴└──┘ └─────┘ ┴ ┴ ┴
doc └──────┘ └──┘ └──┘
2920 begin
st └─────
2921 intros a a' m n,
src └─────────────┘
typ └─────────────┘
doc └─────────────┘
txt └─────────────┘
par └─────────────┘
pid └───────┘
st ────────────────┘└─
2922 by_cases eq : a = a',
id ┴ ┴ └┘
src └───────┘ └─┘ ┴┴┴
typ └───────┘ └─┘┴┴┴┴└┘
doc └───────┘ └─┘ ┴ ┴
txt └───────┘ └─┘ ┴ ┴
par └───────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴
st ─────────────────────┘└─
2923 { subst eq },
id └┘
src └────┘└┘┴
typ └────┘└┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴ ┴
st ───┘└───────┘└┘└
2924 { simp [map_bind, bind_bind (t a') (t a)],
id └──────┘ └───────┘ └┘ ┴ ┴
src └────┘└──────┘└┘└───────┘┴ ┴ └┘ ┴ └┘
typ └────┘└──────┘└┘└───────┘┴ ┴└┘└┘ ┴┴┴└┘
doc └────┘ └┘ ┴ ┴ └┘ ┴ └┘
txt └────┘ └┘ ┴ ┴ └┘ ┴ └┘
par └────┘ └┘ ┴ ┴ └┘ ┴ └┘
pid ┴┴ └┘ ┴ ┴ └┘ ┴ └┘
st ──────────────────────────────────────────┘└─
2925 apply bind_hcongr, { rw [cons_swap a a'] },
id └─────────┘ └───────┘ ┴ └┘
src └────┘└─────────┘ └──┘└───────┘┴ ┴ └┘
typ └────┘└─────────┘ └──┘└───────┘┴┴┴└┘└┘
doc └────┘ └──┘ ┴ ┴ └┘
txt └────┘ └──┘ ┴ ┴ └┘
par └────┘ └──┘ ┴ ┴ └┘
pid ┴ └┘ ┴ ┴ ┴┴
st ────────────────────┘└──┘└────────────────┘┴┴└┘└
2926 intros b hb,
src └─────────┘
typ └─────────┘
doc └─────────┘
txt └─────────┘
par └─────────┘
pid └───┘
st ──────────────┘└─
2927 apply bind_hcongr, { rw [cons_swap a a'] },
id └─────────┘ └───────┘ ┴ └┘
src └────┘└─────────┘ └──┘└───────┘┴ ┴ └┘
typ └────┘└─────────┘ └──┘└───────┘┴┴┴└┘└┘
doc └────┘ └──┘ ┴ ┴ └┘
txt └────┘ └──┘ ┴ ┴ └┘
par └────┘ └──┘ ┴ ┴ └┘
pid ┴ └┘ ┴ ┴ ┴┴
st ────────────────────┘└──┘└────────────────┘┴┴└┘└
2928 intros b' hb',
src └───────────┘
typ └───────────┘
doc └───────────┘
txt └───────────┘
par └───────────┘
pid └─────┘
st ────────────────┘└─
2929 apply map_hcongr, { rw [cons_swap a a'] },
id └────────┘ └───────┘ ┴ └┘
src └────┘└────────┘ └──┘└───────┘┴ ┴ └┘
typ └────┘└────────┘ └──┘└───────┘┴┴┴└┘└┘
doc └────┘ └──┘ ┴ ┴ └┘
txt └────┘ └──┘ ┴ ┴ └┘
par └────┘ └──┘ ┴ ┴ └┘
pid ┴ └┘ ┴ ┴ ┴┴
st ───────────────────┘└──┘└────────────────┘┴┴└┘└
2930 intros f hf,
src └─────────┘
typ └─────────┘
doc └─────────┘
txt └─────────┘
par └─────────┘
pid └───┘
st ──────────────┘└─
2931 exact pi.cons_swap eq }
id └──────────┘ └┘
src └────┘└──────────┘┴└┘┴
typ └────┘└──────────┘┴└┘┴
doc └────┘ ┴ ┴
txt └────┘ ┴ ┴
par └────┘ ┴ ┴
pid ┴ ┴ ┴
st ─────────────────────────┘└─
2932 end
st ──┘
2933
2934 @[simp] lemma pi_zero (t : Πa, multiset (δ a)) : pi 0 t = pi.empty δ :: 0 := rfl
id ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ └──────┘ ┴ └┘ └─┘
src └──────┘ └┘ ┴ └──────┘ └┘ └─┘
typ ┴ └──────┘ ┴ ┴ └┘ ┴ ┴ └──────┘ ┴ └┘ └─┘
doc └──┘ └──────┘ └┘ └┘
2935
2936 @[simp] lemma pi_cons (m : multiset α) (t : Πa, multiset (δ a)) (a : α) :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴ ┴
doc └──┘ └──────┘ └──────┘
2937 pi (a :: m) t = ((t a).bind $ λb, (pi m t).map $ pi.cons m a b) :=
id └┘ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ └┘ ┴ ┴ └─┘ └─────┘ ┴ ┴ ┴
src └┘ └┘ ┴ └──┘ └┘ └─┘ └─────┘
typ └┘ ┴ └┘ ┴ ┴ ┴ ┴ ┴ └──┘ ┴ └┘ ┴ ┴ └─┘ └─────┘ ┴ ┴ ┴
doc └┘ └┘ └──┘ └┘ └─┘
2938 rec_on_cons a m
id └─────────┘ ┴ ┴
src └─────────┘
typ └─────────┘ ┴ ┴
2939
2940 lemma injective_pi_cons {a : α} {b : δ a} {s : multiset α} (hs : a ∉ s) :
id ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──────┘
2941 function.injective (pi.cons s a b) :=
id └────────────────┘ └─────┘ ┴ ┴ ┴
src └────────────────┘ └─────┘
typ └────────────────┘ └─────┘ ┴ ┴ ┴
2942 assume f₁ f₂ eq, funext $ assume a', funext $ assume h',
id └┘ └┘ └┘ └────┘ └┘ └────┘ └┘
src └┘ └────┘ └────┘
typ └┘ └┘ └┘ └────┘ └┘ └────┘ └┘
2943 have ne : a ≠ a', from assume h, hs $ h.symm ▸ h',
id ┴ ┴ └┘ ┴ └┘ ┴└───┘ ┴ └┘
src ┴ └───┘ ┴
typ ┴ ┴ └┘ ┴ └┘ ┴└───┘ ┴ └┘
2944 have a' ∈ a :: s, from mem_cons_of_mem h',
id └┘ ┴ ┴ └┘ ┴ └─────────────┘ └┘
src ┴ └┘ └─────────────┘
typ └┘ ┴ ┴ └┘ ┴ └─────────────┘ └┘
doc └┘
2945 calc f₁ a' h' = pi.cons s a b f₁ a' this : by rw [pi.cons_ne this ne.symm]
id └┘ └┘ └┘ └─────┘ ┴ ┴ ┴ └┘ └┘ └──┘ └────────┘ └──┘ └─────┘
src └─────┘ └──┘└────────┘┴ ┴└─────┘└─
typ └┘ └┘ └┘ └─────┘ ┴ ┴ ┴ └┘ └┘ └──┘ └──┘└────────┘┴└──┘┴└─────┘└─
doc └──┘ ┴ ┴ └─
txt └──┘ ┴ ┴ └─
par └──┘ ┴ ┴ └─
pid └┘ ┴ ┴ ┴└
st └──────────────────────────┘┴└
2946 ... = pi.cons s a b f₂ a' this : by rw [eq]
id └─────┘ ┴ ┴ ┴ └┘ └┘ └──┘ └┘
src ─┘ └─────┘ └──┘└┘└─
typ ─┘ └─────┘ ┴ ┴ ┴ └┘ └┘ └──┘ └──┘└┘└─
doc ─┘ └──┘ └─
txt ─┘ └──┘ └─
par ─┘ └──┘ └─
pid ─┘ └┘ ┴└
st ─┘ └─────┘┴└
2947 ... = f₂ a' h' : by rw [pi.cons_ne this ne.symm]
id └┘ └┘ └┘ └────────┘ └──┘ └─────┘
src ─┘ └──┘└────────┘┴ ┴└─────┘└─
typ ─┘ └┘ └┘ └┘ └──┘└────────┘┴└──┘┴└─────┘└─
doc ─┘ └──┘ ┴ ┴ └─
txt ─┘ └──┘ ┴ ┴ └─
par ─┘ └──┘ ┴ ┴ └─
pid ─┘ └┘ ┴ ┴ ┴└
st ─┘ └──────────────────────────┘┴└
2948
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
2949 lemma card_pi (m : multiset α) (t : Πa, multiset (δ a)) :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘
2950 card (pi m t) = prod (m.map $ λa, card (t a)) :=
id └──┘ └┘ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ └──┘ ┴ ┴
src └──┘ └┘ ┴ └──┘ └──┘ └──┘
typ └──┘ └┘ ┴ ┴ ┴ └──┘ ┴└──┘ ┴ └──┘ ┴ ┴
doc └──┘ └┘ └──┘ └──┘ └──┘
2951 multiset.induction_on m (by simp) (by simp [mul_comm] {contextual := tt})
id └───────────────────┘ ┴ └──────┘ └┘
src └───────────────────┘ └──┘ └────┘└──────┘└┘ └────────────┘└┘┴
typ └───────────────────┘ ┴ └──┘ └────┘└──────┘└┘ └────────────┘└┘┴
doc └──┘ └────┘ └┘ └────────────┘ ┴
txt └──┘ └────┘ └┘ └────────────┘ ┴
par └──┘ └────┘ └┘ └────────────┘ ┴
pid ┴┴ ┴┴ └────────────┘ ┴
st └───┘ └─────────────────────────────────┘
2952
2953 lemma nodup_pi {s : multiset α} {t : Πa, multiset (δ a)} :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘
2954 nodup s → (∀a∈s, nodup (t a)) → nodup (pi s t) :=
id └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ └┘ ┴ ┴
src └───┘ └───┘ └───┘ └┘
typ └───┘ ┴ ┴ ┴ └───┘ ┴ ┴ └───┘ └┘ ┴ ┴
doc └───┘ └───┘ └───┘ └┘
2955 multiset.induction_on s (assume _ _, nodup_singleton _)
id └───────────────────┘ ┴ ┴ ┴ └─────────────┘
src └───────────────────┘ └─────────────┘
typ └───────────────────┘ ┴ ┴ ┴ └─────────────┘
2956 begin
st └─────
2957 assume a s ih hs ht,
src └─────────────────┘
typ └─────────────────┘
doc └─────────────────┘
txt └─────────────────┘
par └─────────────────┘
pid └─────────────────┘
st ────────────────────┘└─
2958 have has : a ∉ s, by simp at hs; exact hs.1,
id ┴ ┴ ┴ └┘
src └─────────┘ ┴┴┴ └────────┘ └────┘ └┘
typ └─────────┘┴┴┴┴┴ └────────┘ └────┘└┘└┘
doc └─────────┘ ┴ ┴ └────────┘ └────┘ └┘
txt └─────────┘ ┴ ┴ └────────┘ └────┘ └┘
par └─────────┘ ┴ ┴ └────────┘ └────┘ └┘
pid └──────┘└─┘ ┴ ┴ ┴└───┘ ┴ └┘
st ─────────────────┘ └─
2959 have hs : nodup s, by simp at hs; exact hs.2,
id └───┘ ┴ └┘
src └────────┘└───┘┴ └────────┘ └────┘ └┘
typ └────────┘└───┘┴┴ └────────┘ └────┘└┘└┘
doc └────────┘└───┘┴ └────────┘ └────┘ └┘
txt └────────┘ ┴ └────────┘ └────┘ └┘
par └────────┘ ┴ └────────┘ └────┘ └┘
pid └─────┘└─┘ ┴ ┴└───┘ ┴ └┘
st ──────────────────┘ └─
2960 simp,
src └──┘
typ └──┘
doc └──┘
txt └──┘
par └──┘
st ─────┘└─
2961 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ──────┘└─
2962 { assume b hb,
src └─────────┘
typ └─────────┘
doc └─────────┘
txt └─────────┘
par └─────────┘
pid └─────────┘
st ───┘└─────────┘└─
2963 from nodup_map (injective_pi_cons has) (ih hs $ assume a' h', ht a' $ mem_cons_of_mem h') },
id └───────┘ └───────────────┘ └─┘ └┘ └┘ └┘ └─────────────┘
src └───┘└───────┘┴ └───────────────┘┴ └┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴└─────────────┘┴ └┘
typ └───┘└───────┘┴ └───────────────┘┴└─┘└┘ └┘┴└┘┴ ┴ └──────┘└┘┴ ┴ ┴└─────────────┘┴ └┘
doc └───┘ ┴ ┴ └┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘
txt └───┘ ┴ ┴ └┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘
par └───┘ ┴ ┴ └┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ └┘
pid └───┘ ┴ ┴ └┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴ ┴┴
st ─────────────────────────────────────────────────────────────────────────────────────────────┘└┘└
2964 { apply pairwise_of_nodup _ (ht a $ mem_cons_self _ _),
id └───────────────┘ └┘ ┴ └───────────┘
src └────┘└───────────────┘└─┘ ┴ ┴ ┴└───────────┘└───┘
typ └────┘└───────────────┘└─┘ └┘┴┴┴ ┴└───────────┘└───┘
doc └────┘ └─┘ ┴ ┴ ┴ └───┘
txt └────┘ └─┘ ┴ ┴ ┴ └───┘
par └────┘ └─┘ ┴ ┴ ┴ └───┘
pid ┴ └─┘ ┴ ┴ ┴ └───┘
st ───────────────────────────────────────────────────────┘└─
2965 from assume b₁ hb₁ b₂ hb₂ neb, disjoint_map_map.2 (assume f hf g hg eq,
id └──────────────┘
src └───┘ └──────────────────┘└──────────────┘└─┘ └──────────────
typ └───┘ └──────────────────┘└──────────────┘└─┘ └──────────────
doc └───┘ └──────────────────┘ └─┘ └──────────────
txt └───┘ └──────────────────┘ └─┘ └──────────────
par └───┘ └──────────────────┘ └─┘ └──────────────
pid └───┘ └──────────────────┘ └─┘ └──────────────
st ────────────────────────────────────────────────────────────────────────────
2966 have pi.cons s a b₁ f a (mem_cons_self _ _) = pi.cons s a b₂ g a (mem_cons_self _ _),
id ┴ └─────┘ ┴ ┴ └───────────┘
src ─────┘ └───────┘ ┴ ┴ ┴ ┴ ┴ └────┘┴┴└─────┘┴ ┴ ┴ ┴ ┴ ┴ └───────────┘└──────
typ ─────┘ └───────┘ ┴ ┴ ┴ ┴ ┴ └────┘┴┴└─────┘┴┴┴ ┴ ┴ ┴┴┴ └───────────┘└──────
doc ─────┘ └───────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────
txt ─────┘ └───────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────
par ─────┘ └───────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────
pid ─────┘ └───────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────
st ────────────────────────────────────────────────────────────────────────────────────────────
2967 by rw [eq],
id └┘
src ──────────┘└──┘└┘┴└─
typ ──────────┘└──┘└┘┴└─
doc ──────────┘└──┘ ┴└─
txt ──────────┘└──┘ ┴└─
par ──────────┘└──┘ ┴└─
pid ──────────────┘ └──
st ─────────┘└─────┘┴└─
2968 neb $ show b₁ = b₂, by rwa [pi.cons_same, pi.cons_same] at this) }
id ┴ └──────────┘ └──────────┘
src ─────┘ ┴ ┴ ┴ ┴ ┴ └───┘└───┘└──────────┘└┘└──────────┘└───────┘└┘
typ ─────┘ ┴ ┴ ┴ ┴┴┴ └───┘└───┘└──────────┘└┘└──────────┘└───────┘└┘
doc ─────┘ ┴ ┴ ┴ ┴ ┴ └───┘└───┘ └┘ └───────┘└┘
txt ─────┘ ┴ ┴ ┴ ┴ ┴ └───┘└───┘ └┘ └───────┘└┘
par ─────┘ ┴ ┴ ┴ ┴ ┴ └───┘└───┘ └┘ └───────┘└┘
pid ─────┘ ┴ ┴ ┴ ┴ ┴ └────────┘ └┘ └────────┘┴
st ───────────────────────────┘└────────────────┘└────────────┘┴└──────┘└┘└─
2969 end
st ──┘
2970
2971 lemma mem_pi (m : multiset α) (t : Πa, multiset (δ a)) :
id └──────┘ ┴ ┴ └──────┘ ┴ ┴
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └──────┘ ┴ ┴
doc └──────┘ └──────┘
2972 ∀f:Πa∈m, δ a, (f ∈ pi m t) ↔ (∀a (h : a ∈ m), f a h ∈ t a) :=
id ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └┘ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └┘
2973 begin
st └─────
2974 refine multiset.induction_on m (λ f, _) (λ a m ih f, _),
id └───────────────────┘ ┴
src └─────┘└───────────────────┘┴ ┴ └─────┘ └───────────┘
typ └─────┘└───────────────────┘┴┴┴ └─────┘ └───────────┘
doc └─────┘ ┴ ┴ └─────┘ └───────────┘
txt └─────┘ ┴ ┴ └─────┘ └───────────┘
par └─────┘ ┴ ┴ └─────┘ └───────────┘
pid ┴ ┴ ┴ └─────┘ └───────────┘
st ────────────────────────────────────────────────────────┘└─
2975 { simpa using show f = pi.empty δ, by funext a ha; exact ha.elim },
id ┴ ┴ └──────┘ ┴ └─────┘
src └──────────┘ ┴ ┴┴┴└──────┘┴ └───┘└─────────┘└┘└────┘└─────┘┴
typ └──────────┘ ┴┴┴┴┴└──────┘┴┴└───┘└─────────┘└┘└────┘└─────┘┴
doc └──────────┘ ┴ ┴ ┴ ┴ └───┘└─────────┘└┘└────┘ ┴
txt └──────────┘ ┴ ┴ ┴ ┴ └───┘└─────────┘└┘└────┘ ┴
par └──────────┘ ┴ ┴ ┴ ┴ └───┘└─────────┘└┘└────┘ ┴
pid ┴└────┘ ┴ ┴ ┴ ┴ └──────────────────────┘ ┴
st ───┘└─────────────────────────────────┘└──────────────────────────┘└┘└
2976 simp, split,
src └──┘ └───┘
typ └──┘ └───┘
doc └──┘ └───┘
txt └──┘ └───┘
par └──┘ └───┘
st ─────┘└─────┘└─
2977 { rintro ⟨b, hb, f', hf', rfl⟩ a' ha',
src └─────────────────────────────────┘
typ └─────────────────────────────────┘
doc └─────────────────────────────────┘
txt └─────────────────────────────────┘
par └─────────────────────────────────┘
pid └───────────────────────────┘
st ───┘└─────────────────────────────────┘└─
2978 rw [ih] at hf',
id └┘
src └──┘ └──────┘
typ └──┘└┘└──────┘
doc └──┘ └──────┘
txt └──┘ └──────┘
par └──┘ └──────┘
pid └┘ ┴└─────┘
st ─────────┘┴└─────┘└─
2979 by_cases a' = a,
id └┘ ┴
src └───────┘ ┴ ┴
typ └───────┘└┘┴ ┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ──────────────────┘└─
2980 { subst h, rwa [pi.cons_same] },
id ┴ └──────────┘
src └────┘ └───┘└──────────┘└┘
typ └────┘┴ └───┘└──────────┘└┘
doc └────┘ └───┘ └┘
txt └────┘ └───┘ └┘
par └────┘ └───┘ └┘
pid ┴ └┘ ┴┴
st ─────┘└─────┘└─────────────────┘┴┴└┘└
2981 { rw [pi.cons_ne _ h], apply hf' } },
id └────────┘ ┴
src └──┘└────────┘└─┘ ┴ └────┘ ┴
typ └──┘└────────┘└─┘┴┴ └────┘ ┴
doc └──┘ └─┘ ┴ └────┘ ┴
txt └──┘ └─┘ ┴ └────┘ ┴
par └──┘ └─┘ ┴ └────┘ ┴
pid └┘ └─┘ ┴ ┴ ┴
st ───────────────────────┘└───────────┘└──┘└
2982 { intro hf,
src └──────┘
typ └──────┘
doc └──────┘
txt └──────┘
par └──────┘
pid └─┘
st ───────────┘└─
2983 refine ⟨_, hf a (mem_cons_self a _), λa ha, f a (mem_cons_of_mem ha),
id └───────────┘ ┴ ┴ └─────────────┘
src └─────┘ └─┘ ┴ ┴ └───────────┘┴ └───┘ └────┘ ┴ ┴ └─────────────┘┴ └──
typ └─────┘ └─┘ ┴ ┴ └───────────┘┴┴└───┘ └────┘┴┴ ┴ └─────────────┘┴ └──
doc └─────┘ └─┘ ┴ ┴ ┴ └───┘ └────┘ ┴ ┴ ┴ └──
txt └─────┘ └─┘ ┴ ┴ ┴ └───┘ └────┘ ┴ ┴ ┴ └──
par └─────┘ └─┘ ┴ ┴ ┴ └───┘ └────┘ ┴ ┴ ┴ └──
pid ┴ └─┘ ┴ ┴ ┴ └───┘ └────┘ ┴ ┴ ┴ └──
st ──────────────────────────────────────────────────────────────────────────
2984 (ih _).2 (λ a' h', hf _ _), _⟩,
id └┘ └┘
src ─────┘ └────┘ └──────┘ └───────┘
typ ─────┘ └┘└────┘ └──────┘└┘└───────┘
doc ─────┘ └────┘ └──────┘ └───────┘
txt ─────┘ └────┘ └──────┘ └───────┘
par ─────┘ └────┘ └──────┘ └───────┘
pid ─────┘ └────┘ └──────┘ └───────┘
st ───────────────────────────────────┘└─
2985 funext a' h',
src └──────────┘
typ └──────────┘
doc └──────────┘
txt └──────────┘
par └──────────┘
pid └────┘
st ───────────────┘└─
2986 by_cases a' = a,
id └┘ ┴
src └───────┘ ┴ ┴
typ └───────┘└┘┴ ┴┴
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ──────────────────┘└─
2987 { subst h, rw [pi.cons_same] },
id ┴ └──────────┘
src └────┘ └──┘└──────────┘└┘
typ └────┘┴ └──┘└──────────┘└┘
doc └────┘ └──┘ └┘
txt └────┘ └──┘ └┘
par └────┘ └──┘ └┘
pid ┴ └┘ ┴┴
st ─────┘└─────┘└────────────────┘┴┴└┘└
2988 { rw [pi.cons_ne _ h] } }
id └────────┘ ┴
src └──┘└────────┘└─┘ └┘
typ └──┘└────────┘└─┘┴└┘
doc └──┘ └─┘ └┘
txt └──┘ └─┘ └┘
par └──┘ └─┘ └┘
pid └┘ └─┘ ┴┴
st ───────────────────────┘┴┴└───
2989 end
st ──┘
2990
2991 end pi
2992 end multiset
2993
2994 namespace multiset
2995
2996 instance : functor multiset :=
id └─────┘ └──────┘
src └─────┘ └──────┘
typ └─────┘ └──────┘
doc └──────┘
2997 { map := @map }
id └─┘
src └─┘
typ └─┘
doc └─┘
2998
2999 instance : is_lawful_functor multiset :=
id └───────────────┘ └──────┘
src └───────────────┘ └──────┘
typ └───────────────┘ └──────┘
doc └──────┘
3000 by refine { .. }; intros; simp
id ┴
src └─────┘┴└───┘ └────┘ └────
typ └─────┘┴└───┘ └────┘ └────
doc └─────┘ └───┘ └────┘ └────
txt └─────┘ └───┘ └────┘ └────
par └─────┘ └───┘ └────┘ └────
pid ┴ └───┘ └
st └────────────────────────────
3001
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
3002 open is_lawful_traversable is_comm_applicative
3003
3004 variables {F : Type u_1 → Type u_1} [applicative F] [is_comm_applicative F]
id └──┘ └─────────┘ └─────────────────┘
src └─────────┘ └─────────────────┘
typ └──┘ └─────────┘ └─────────────────┘
3005 variables {α' β' : Type u_1} (f : α' → F β')
3006
3007 def traverse : multiset α' → F (multiset β') :=
id └──────┘ └┘ ┴ └──────┘ └┘
src └──────┘ └──────┘
typ └──────┘ └┘ ┴ └──────┘ └┘
doc └──────┘ └──────┘
3008 quotient.lift (functor.map coe ∘ traversable.traverse f)
id └───────────┘ └─────────┘ └─┘ ┴ └──────────────────┘ ┴
src └───────────┘ └─────────┘ └─┘ ┴ └──────────────────┘
typ └───────────┘ └─────────┘ └─┘ ┴ └──────────────────┘ ┴
3009 begin
st └─────
3010 introv p, unfold function.comp,
src └──────┘ └──────────────────┘
typ └──────┘ └──────────────────┘
doc └──────┘ └──────────────────┘
txt └──────┘ └──────────────────┘
par └──────┘ └──────────────────┘
pid └┘ └────────────┘
st ─────────┘└────────────────────┘└─
3011 induction p,
id ┴
src └────────┘
typ └────────┘┴
doc └────────┘
txt └────────┘
par └────────┘
pid ┴
st ────────────┘└─
3012 case perm.nil { refl },
src └──────────────┘└───┘┴
typ └──────────────┘└───┘┴
doc └──────────────┘└───┘┴
txt └──────────────┘└───┘┴
par └──────────────┘└───┘┴
pid └───────┘┴└──────┘
st ────────────────┘└────┘└┘└
3013 case perm.skip {
src └────────────────
typ └────────────────
doc └────────────────
txt └────────────────
par └────────────────
pid └────────┘┴└─
st ─────────────────┘└
3014 have : multiset.cons <$> f p_x <*> (coe <$> traverse f p_l₁) =
id └─┘ └─┘ └──┘ ┴
src ───┘└─────┘ ┴└─┘┴ ┴ ┴└─┘┴ ┴ ┴ ┴ ┴ └┘┴└
typ ───┘└─────┘ ┴└─┘┴ ┴ ┴└─┘┴ ┴ ┴ ┴ ┴└──┘└┘┴└
doc ───┘└─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ └
txt ───┘└─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ └
par ───┘└─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ └
pid ──────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ └
st ───────────────────────────────────────────────────────────────────
3015 multiset.cons <$> f p_x <*> (coe <$> traverse f p_l₂),
id └───────────┘ └─┘ └─┘ └──────┘ ┴ └──┘
src ─────┘└───────────┘┴ ┴ ┴ ┴ ┴ └─┘┴ ┴└──────┘┴ ┴ ┴└─
typ ─────┘└───────────┘┴ ┴ ┴└─┘┴ ┴ └─┘┴ ┴└──────┘┴┴┴└──┘┴└─
doc ─────┘└───────────┘┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└─
txt ─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└─
par ─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴└─
pid ─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──
st ──────────────────────────────────────────────────────────┘└─
3016 { rw [p_ih] },
id └──┘
src ─────┘└──┘ └┘└──
typ ─────┘└──┘└──┘└┘└──
doc ─────┘└──┘ └┘└──
txt ─────┘└──┘ └┘└──
par ─────┘└──┘ └┘└──
pid ─────────┘ └────
st ────┘└───────┘┴┴┴└─
3017 simpa with functor_norm },
src ───┘└──────────────────────┘┴
typ ───┘└──────────────────────┘┴
doc ───┘└──────────────────────┘┴
txt ───┘└──────────────────────┘┴
par ───┘└──────────────────────┘┴
pid ────────────────────────────┘
st ───────────────────────────┘└┘└
3018 case perm.swap {
src └────────────────
typ └────────────────
doc └────────────────
txt └────────────────
par └────────────────
pid └────────┘┴└─
st ─────────────────┘└
3019 have : (λa b (l:list β'), (↑(a :: b :: l) : multiset β')) <$> f p_y <*> f p_x =
id └──┘ └──────┘ └┘
src ───┘└─────┘ └─────┘└──┘┴ └─┘ ┴ ┴ ┴ ┴ └──┘└──────┘┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ └
typ ───┘└─────┘ └─────┘└──┘┴ └─┘ ┴ ┴ ┴ ┴ └──┘└──────┘┴└┘└─┘ ┴ ┴ ┴ ┴ ┴ ┴ └
doc ───┘└─────┘ └─────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └──┘└──────┘┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ └
txt ───┘└─────┘ └─────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └──┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ └
par ───┘└─────┘ └─────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └──┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ └
pid ──────────┘ └─────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └──┘ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ └
st ────────────────────────────────────────────────────────────────────────────────────
3020 (λa b l, ↑(a :: b :: l)) <$> f p_x <*> f p_y,
id └─┘ ┴ └─┘
src ─────┘ └─────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─
typ ─────┘ └─────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴└─┘┴ ┴┴┴└─┘└─
doc ─────┘ └─────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─
txt ─────┘ └─────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─
par ─────┘ └─────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─
pid ─────┘ └─────┘ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─
st ─────────────────────────────────────────────────┘└─
3021 { rw [is_comm_applicative.commutative_map],
id └─────────────────────────────────┘
src ─────┘└──┘└─────────────────────────────────┘┴└─
typ ─────┘└──┘└─────────────────────────────────┘┴└─
doc ─────┘└──┘ ┴└─
txt ─────┘└──┘ ┴└─
par ─────┘└──┘ ┴└─
pid ─────────┘ └──
st ────┘└──────────────────────────────────────┘└──
3022 congr, funext a b l, simpa [flip] using perm.swap b a l },
id └──┘ └───────┘ ┴ ┴ ┴
src ─────┘└───┘└┘└──────────┘└┘└─────┘└──┘└──────┘└───────┘┴ ┴ ┴ ┴└──
typ ─────┘└───┘└┘└──────────┘└┘└─────┘└──┘└──────┘└───────┘┴┴┴┴┴┴┴└──
doc ─────┘ └┘└──────────┘└┘└─────┘ └──────┘ ┴ ┴ ┴ ┴└──
txt ─────┘└───┘└┘└──────────┘└┘└─────┘ └──────┘ ┴ ┴ ┴ ┴└──
par ─────┘└───┘└┘└──────────┘└┘└─────┘ └──────┘ ┴ ┴ ┴ ┴└──
pid ─────────────────────────────────┘ └──────┘ ┴ ┴ ┴ └───
st ──────────┘└────────────┘└───────────────────────────────────┘┴└─
3023 simp [(∘), this] with functor_norm },
id ┴ └──┘
src ───┘└────┘┴└──┘ └──────────────────┘┴
typ ───┘└────┘┴└──┘└──┘└──────────────────┘┴
doc ───┘└────┘ └──┘ └──────────────────┘┴
txt ───┘└────┘ └──┘ └──────────────────┘┴
par ───┘└────┘ └──┘ └──────────────────┘┴
pid ─────────┘ └──┘ └───────────────────┘
st ──────────────────────────────────────┘└┘└
3024 case perm.trans { simp [*] }
src └────────────────┘└───────┘└┘
typ └────────────────┘└───────┘└┘
doc └────────────────┘└───────┘└┘
txt └────────────────┘└───────┘└┘
par └────────────────┘└───────┘└┘
pid └─────────┘┴└──────────┘┴
st ────────────────────────────┘┴┴
3025 end
st └─┘
3026
3027 instance : monad multiset :=
id └───┘ └──────┘
src └───┘ └──────┘
typ └───┘ └──────┘
doc └──────┘
3028 { pure := λ α x, x::0,
id ┴ ┴ ┴└┘
src └┘
typ ┴ ┴ ┴└┘
doc └┘
3029 bind := @bind,
id └──┘
src └──┘
typ └──┘
doc └──┘
3030 .. multiset.functor }
id └──────────────┘
src └──────────────┘
typ └──────────────┘
3031
3032 instance : is_lawful_monad multiset :=
id └─────────────┘ └──────┘
src └─────────────┘ └──────┘
typ └─────────────┘ └──────┘
doc └──────┘
3033 { bind_pure_comp_eq_map := λ α β f s, multiset.induction_on s rfl $ λ a s ih,
id ┴ ┴ ┴ ┴ ┴ └───────────────────┘ ┴ └─┘ ┴ ┴ └┘
src ┴ └───────────────────┘ └─┘
typ ┴ ┴ ┴ ┴ ┴ └───────────────────┘ ┴ └─┘ ┴ ┴ └┘
3034 by rw [bind_cons, map_cons, bind_zero, add_zero],
id └───────┘ └──────┘ └───────┘ └──────┘
src └──┘└───────┘└┘└──────┘└┘└───────┘└┘└──────┘┴
typ └──┘└───────┘└┘└──────┘└┘└───────┘└┘└──────┘┴
doc └──┘ └┘ └┘ └┘ ┴
txt └──┘ └┘ └┘ └┘ ┴
par └──┘ └┘ └┘ └┘ ┴
pid └┘ └┘ └┘ └┘ ┴
st └────────────┘└────────┘└─────────┘└────────┘┴
3035 pure_bind := λ α β x f, by simp only [cons_bind, zero_bind, add_zero],
id ┴ ┴ ┴ ┴ └───────┘ └───────┘ └──────┘
src └─────────┘└───────┘└┘└───────┘└┘└──────┘┴
typ ┴ ┴ ┴ ┴ └─────────┘└───────┘└┘└───────┘└┘└──────┘┴
doc └─────────┘ └┘ └┘ ┴
txt └─────────┘ └┘ └┘ ┴
par └─────────┘ └┘ └┘ ┴
pid ┴└──┘└┘ └┘ └┘ ┴
st └─────────────────────────────────────────┘
3036 bind_assoc := @bind_assoc }
id └────────┘
src └────────┘
typ └────────┘
3037
3038 open functor
3039 open traversable is_lawful_traversable
3040
3041 @[simp]
doc └──┘
3042 lemma lift_beta {α β : Type*} (x : list α) (f : list α → β)
id └──┘ ┴ └──┘ ┴ ┴
src └──┘ └──┘
typ └──┘ ┴ └──┘ ┴ ┴
3043 (h : ∀ a b : list α, a ≈ b → f a = f b) :
id └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──┘ ┴ ┴
typ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
3044 quotient.lift f h (x : multiset α) = f x :=
id └───────────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
src └───────────┘ └──────┘ ┴
typ └───────────┘ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴ ┴
doc └──────┘
3045 quotient.lift_beta _ _ _
id └────────────────┘
src └────────────────┘
typ └────────────────┘
3046
3047 @[simp]
doc └──┘
3048 lemma map_comp_coe {α β} (h : α → β) :
id ┴ ┴
typ ┴ ┴
3049 functor.map h ∘ coe = (coe ∘ functor.map h : list α → multiset β) :=
id └─────────┘ ┴ ┴ └─┘ ┴ └─┘ ┴ └─────────┘ ┴ └──┘ ┴ └──────┘ ┴
src └─────────┘ ┴ └─┘ ┴ └─┘ ┴ └─────────┘ └──┘ └──────┘
typ └─────────┘ ┴ ┴ └─┘ ┴ └─┘ ┴ └─────────┘ ┴ └──┘ ┴ └──────┘ ┴
doc └──────┘
3050 by funext; simp [functor.map]
src └────┘ └────┘ └─
typ └────┘ └────┘ └─
doc └────┘ └────┘ └─
txt └────┘ └────┘ └─
par └────┘ └────┘ └─
pid ┴┴ ┴└
st └───────────────────────────
3051
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
3052 lemma id_traverse {α : Type*} (x : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
3053 traverse id.mk x = x :=
id └──────┘ └───┘ ┴ ┴ ┴
src └──────┘ └───┘ ┴
typ └──────┘ └───┘ ┴ ┴ ┴
3054 quotient.induction_on x
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
3055 (by { intro, rw [traverse,quotient.lift_beta,function.comp],
id └──────┘ └────────────────┘ └───────────┘
src └───┘ └──┘└──────┘┴└────────────────┘┴└───────────┘┴
typ └───┘ └──┘└──────┘┴└────────────────┘┴└───────────┘┴
doc └───┘ └──┘ ┴ ┴ ┴
txt └───┘ └──┘ ┴ ┴ ┴
par └───┘ └──┘ ┴ ┴ ┴
pid └┘ ┴ ┴ ┴
st └──────┘└────────────┘└─────────────────┘└────────────┘└──
3056 simp, congr })
src └──┘ └────┘
typ └──┘ └────┘
doc └──┘
txt └──┘ └────┘
par └──┘ └────┘
pid ┴
st ─────────┘└──────┘└┘
3057
3058 lemma comp_traverse {G H : Type* → Type*}
id └───┘
typ └───┘
3059 [applicative G] [applicative H]
id └─────────┘ ┴ └─────────┘ ┴
src └─────────┘ └─────────┘
typ └─────────┘ ┴ └─────────┘ ┴
3060 [is_comm_applicative G] [is_comm_applicative H]
id └─────────────────┘ ┴ └─────────────────┘ ┴
src └─────────────────┘ └─────────────────┘
typ └─────────────────┘ ┴ └─────────────────┘ ┴
3061 {α β γ : Type*}
3062 (g : α → G β) (h : β → H γ) (x : multiset α) :
id ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
3063 traverse (comp.mk ∘ functor.map h ∘ g) x =
id └──────┘ └─────┘ ┴ └─────────┘ ┴ ┴ ┴ ┴ ┴
src └──────┘ └─────┘ ┴ └─────────┘ ┴ ┴
typ └──────┘ └─────┘ ┴ └─────────┘ ┴ ┴ ┴ ┴ ┴
3064 comp.mk (functor.map (traverse h) (traverse g x)) :=
id └─────┘ └─────────┘ └──────┘ ┴ └──────┘ ┴ ┴
src └─────┘ └─────────┘ └──────┘ └──────┘
typ └─────┘ └─────────┘ └──────┘ ┴ └──────┘ ┴ ┴
3065 quotient.induction_on x
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
3066 (by intro;
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st └───────
3067 simp [traverse,comp_traverse] with functor_norm;
id └──────┘ └───────────┘
src └────┘└──────┘┴└───────────┘└─────────────────┘
typ └────┘└──────┘┴└───────────┘└─────────────────┘
doc └────┘ ┴ └─────────────────┘
txt └────┘ ┴ └─────────────────┘
par └────┘ ┴ └─────────────────┘
pid ┴┴ ┴ ┴└────────────────┘
st ─────────────────────────────────────────────────────
3068 simp [(<$>),(∘)] with functor_norm)
id ┴
src └────┘ └───┘┴└───────────────────┘
typ └────┘ └───┘┴└───────────────────┘
doc └────┘ └───┘ └───────────────────┘
txt └────┘ └───┘ └───────────────────┘
par └────┘ └───┘ └───────────────────┘
pid ┴┴ └───┘ └─┘└────────────────┘
st ─────────────────────────────────────┘
3069
3070 lemma map_traverse {G : Type* → Type*}
id └───┘
typ └───┘
3071 [applicative G] [is_comm_applicative G]
id └─────────┘ ┴ └─────────────────┘ ┴
src └─────────┘ └─────────────────┘
typ └─────────┘ ┴ └─────────────────┘ ┴
3072 {α β γ : Type*}
3073 (g : α → G β) (h : β → γ)
id ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴
3074 (x : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
3075 functor.map (functor.map h) (traverse g x) =
id └─────────┘ └─────────┘ ┴ └──────┘ ┴ ┴ ┴
src └─────────┘ └─────────┘ └──────┘ ┴
typ └─────────┘ └─────────┘ ┴ └──────┘ ┴ ┴ ┴
3076 traverse (functor.map h ∘ g) x :=
id └──────┘ └─────────┘ ┴ ┴ ┴ ┴
src └──────┘ └─────────┘ ┴
typ └──────┘ └─────────┘ ┴ ┴ ┴ ┴
3077 quotient.induction_on x
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
3078 (by intro; simp [traverse] with functor_norm;
id └──────┘
src └───┘ └────┘└──────┘└─────────────────┘
typ └───┘ └────┘└──────┘└─────────────────┘
doc └───┘ └────┘ └─────────────────┘
txt └───┘ └────┘ └─────────────────┘
par └───┘ └────┘ └─────────────────┘
pid ┴┴ ┴└────────────────┘
st └──────────────────────────────────────────
3079 rw [comp_map,map_traverse])
id └──────┘ └──────────┘
src └──┘└──────┘┴└──────────┘┴
typ └──┘└──────┘┴└──────────┘┴
doc └──┘ ┴ ┴
txt └──┘ ┴ ┴
par └──┘ ┴ ┴
pid └┘ ┴ ┴
st ───────┘└──────┘└───────────┘┴
3080
3081 lemma traverse_map {G : Type* → Type*}
id └───┘
typ └───┘
3082 [applicative G] [is_comm_applicative G]
id └─────────┘ ┴ └─────────────────┘ ┴
src └─────────┘ └─────────────────┘
typ └─────────┘ ┴ └─────────────────┘ ┴
3083 {α β γ : Type*}
3084 (g : α → β) (h : β → G γ)
id ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴
3085 (x : multiset α) :
id └──────┘ ┴
src └──────┘
typ └──────┘ ┴
doc └──────┘
3086 traverse h (map g x) =
id └──────┘ ┴ └─┘ ┴ ┴ ┴
src └──────┘ └─┘ ┴
typ └──────┘ ┴ └─┘ ┴ ┴ ┴
doc └─┘
3087 traverse (h ∘ g) x :=
id └──────┘ ┴ ┴ ┴ ┴
src └──────┘ ┴
typ └──────┘ ┴ ┴ ┴ ┴
3088 quotient.induction_on x
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
3089 (by intro; simp [traverse];
id └──────┘
src └───┘ └────┘└──────┘┴
typ └───┘ └────┘└──────┘┴
doc └───┘ └────┘ ┴
txt └───┘ └────┘ ┴
par └───┘ └────┘ ┴
pid ┴┴ ┴
st └────────────────────────
3090 rw [← traversable.traverse_map h g];
id └──────────────────────┘ ┴ ┴
src └────┘└──────────────────────┘┴ ┴ ┴
typ └────┘└──────────────────────┘┴┴┴┴┴
doc └────┘ ┴ ┴ ┴
txt └────┘ ┴ ┴ ┴
par └────┘ ┴ ┴ ┴
pid └──┘ ┴ ┴ ┴
st ───────┘└────────────────────────────┘┴└─
3091 [ refl, apply_instance ])
id ┴
src ┴ └──┘ └─────────────┘
typ ┴ └──┘ └─────────────┘
doc └──┘ └─────────────┘
txt └──┘ └─────────────┘
par └──┘ └─────────────┘
pid ┴
st ───────────────────────────┘
3092
3093 lemma naturality {G H : Type* → Type*}
id └───┘
typ └───┘
3094 [applicative G] [applicative H]
id └─────────┘ ┴ └─────────┘ ┴
src └─────────┘ └─────────┘
typ └─────────┘ ┴ └─────────┘ ┴
3095 [is_comm_applicative G] [is_comm_applicative H]
id └─────────────────┘ ┴ └─────────────────┘ ┴
src └─────────────────┘ └─────────────────┘
typ └─────────────────┘ ┴ └─────────────────┘ ┴
3096 (eta : applicative_transformation G H)
id └────────────────────────┘ ┴ ┴
src └────────────────────────┘
typ └────────────────────────┘ ┴ ┴
3097 {α β : Type*} (f : α → G β) (x : multiset α) :
id ┴ ┴ ┴ └──────┘ ┴
src └──────┘
typ ┴ ┴ ┴ └──────┘ ┴
doc └──────┘
3098 eta (traverse f x) = traverse (@eta _ ∘ f) x :=
id └─┘ └──────┘ ┴ ┴ ┴ └──────┘ └─┘ ┴ ┴ ┴
src └──────┘ ┴ └──────┘ ┴
typ └─┘ └──────┘ ┴ ┴ ┴ └──────┘ └─┘ ┴ ┴ ┴
3099 quotient.induction_on x
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
3100 (by intro; simp [traverse,is_lawful_traversable.naturality] with functor_norm)
id └──────┘ └──────────────────────────────┘
src └───┘ └────┘└──────┘┴└──────────────────────────────┘└─────────────────┘
typ └───┘ └────┘└──────┘┴└──────────────────────────────┘└─────────────────┘
doc └───┘ └────┘ ┴ └─────────────────┘
txt └───┘ └────┘ ┴ └─────────────────┘
par └───┘ └────┘ ┴ └─────────────────┘
pid ┴┴ ┴ ┴└────────────────┘
st └────────────────────────────────────────────────────────────────────────┘
3101
3102 section choose
3103 variables (p : α → Prop) [decidable_pred p] (l : multiset α)
id └────────────┘ └──────┘
src └────────────┘ └──────┘
typ └────────────┘ └──────┘
doc └──────┘
3104
3105 def choose_x : Π hp : (∃! a, a ∈ l ∧ p a), { a // a ∈ l ∧ p a } :=
id └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └┘ ┴ ┴ ┴ ┴ ┴ ┴
typ └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
3106 quotient.rec_on l (λ l' ex_unique, list.choose_x p l' (exists_of_exists_unique ex_unique)) begin
id └─────────────┘ ┴ └┘ └───────┘ └───────────┘ ┴ └┘ └─────────────────────┘ └───────┘
src └─────────────┘ └───────────┘ └─────────────────────┘
typ └─────────────┘ ┴ └┘ └───────┘ └───────────┘ ┴ └┘ └─────────────────────┘ └───────┘
st └─────
3107 intros,
src └────┘
typ └────┘
doc └────┘
txt └────┘
par └────┘
st ───────┘└─
3108 funext hp,
src └───────┘
typ └───────┘
doc └───────┘
txt └───────┘
par └───────┘
pid └─┘
st ──────────┘└─
3109 suffices all_equal : ∀ x y : { t // t ∈ b ∧ p t }, x = y,
id ┴ ┴ ┴ ┴ ┴
src └───────────────────┘ └─────┘┴└────┘ ┴┴┴ ┴ ┴ ┴ └┘ ┴ ┴┴┴
typ └───────────────────┘ └─────┘┴└────┘ ┴┴┴┴┴ ┴┴┴ └┘ ┴ ┴┴┴
doc └───────────────────┘ └─────┘ └────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
txt └───────────────────┘ └─────┘ └────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
par └───────────────────┘ └─────┘ └────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
pid └────────────────┘└─┘ └─────┘ └────┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
st ─────────────────────────────────────────────────────────┘└─
3110 { apply all_equal },
src └────┘ ┴
typ └────┘ ┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴ ┴
st ───┘└──────────────┘└┘└
3111 { rintros ⟨x, px⟩ ⟨y, py⟩,
src └─────────────────────┘
typ └─────────────────────┘
doc └─────────────────────┘
txt └─────────────────────┘
par └─────────────────────┘
pid └──────────────┘
st ──────────────────────────┘└─
3112 rcases hp with ⟨z, ⟨z_mem_l, pz⟩, z_unique⟩,
id └┘
src └─────┘ └────────────────────────────────┘
typ └─────┘└┘└────────────────────────────────┘
doc └─────┘ └────────────────────────────────┘
txt └─────┘ └────────────────────────────────┘
par └─────┘ └────────────────────────────────┘
pid ┴ └────────────────────────────────┘
st ──────────────────────────────────────────────┘└─
3113 congr,
src └───┘
typ └───┘
txt └───┘
par └───┘
st ────────┘└─
3114 calc x = z : z_unique x px
id └──┘ ┴ ┴ └┘
src └──┘
typ └──┘ ┴ ┴ └┘
doc └──┘
st ───────────────────────────────
3115 ... = y : (z_unique y py).symm }
id └──────┘ ┴ └┘ └──┘
src └──┘
typ └──────┘ ┴ └┘ └──┘
st ───────────────────────────────────┘└───
3116 end
st ──┘
3117
3118 def choose (hp : ∃! a, a ∈ l ∧ p a) : α := choose_x p l hp
id └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └┘
src └┘ ┴ ┴ ┴ └──────┘
typ └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ └┘
3119
3120 lemma choose_spec (hp : ∃! a, a ∈ l ∧ p a) : choose p l hp ∈ l ∧ p (choose p l hp) :=
id └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘
src └┘ ┴ ┴ ┴ └────┘ ┴ ┴ └────┘
typ └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘
3121 (choose_x p l hp).property
id └──────┘ ┴ ┴ └┘ └──────┘
src └──────┘ └──────┘
typ └──────┘ ┴ ┴ └┘ └──────┘
3122
3123 lemma choose_mem (hp : ∃! a, a ∈ l ∧ p a) : choose p l hp ∈ l := (choose_spec _ _ _).1
id └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘ ┴ ┴ └─────────┘ ┴
src └┘ ┴ ┴ ┴ └────┘ ┴ └─────────┘ ┴
typ └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘ ┴ ┴ └─────────┘ ┴
3124
3125 lemma choose_property (hp : ∃! a, a ∈ l ∧ p a) : p (choose p l hp) := (choose_spec _ _ _).2
id └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘ └─────────┘ ┴
src └┘ ┴ ┴ ┴ └────┘ └─────────┘ ┴
typ └┘ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └┘ └─────────┘ ┴
3126
3127 end choose
3128
3129 /- Ico -/
3130
3131 /-- `Ico n m` is the multiset lifted from the list `Ico n m`, e.g. the set `{n, n+1, ..., m-1}`. -/
3132 def Ico (n m : ℕ) : multiset ℕ := Ico n m
id ┴ └──────┘ ┴ └─┘ ┴ ┴
src ┴ └──────┘ ┴ └─┘
typ ┴ └──────┘ ┴ └─┘ ┴ ┴
doc └──────┘ └─┘
3133
3134 namespace Ico
3135
3136 theorem map_add (n m k : ℕ) : (Ico n m).map ((+) k) = Ico (n + k) (m + k) :=
id ┴ └─┘ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └─┘ └─┘ ┴ ┴ └─┘ ┴ ┴
typ ┴ └─┘ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └─┘ └─┘
3137 congr_arg coe $ list.Ico.map_add _ _ _
id └───────┘ └─┘ └──────────────┘
src └───────┘ └─┘ └──────────────┘
typ └───────┘ └─┘ └──────────────┘
3138
3139 theorem map_sub (n m k : ℕ) (h : k ≤ n) : (Ico n m).map (λ x, x - k) = Ico (n - k) (m - k) :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ └─┘ └─┘ ┴ ┴ └─┘ ┴ ┴
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └─┘ └─┘
3140 congr_arg coe $ list.Ico.map_sub _ _ _ h
id └───────┘ └─┘ └──────────────┘ ┴
src └───────┘ └─┘ └──────────────┘
typ └───────┘ └─┘ └──────────────┘ ┴
3141
3142 theorem zero_bot (n : ℕ) : Ico 0 n = range n :=
id ┴ └─┘ ┴ ┴ └───┘ ┴
src ┴ └─┘ ┴ └───┘
typ ┴ └─┘ ┴ ┴ └───┘ ┴
doc └─┘ └───┘
3143 congr_arg coe $ list.Ico.zero_bot _
id └───────┘ └─┘ └───────────────┘
src └───────┘ └─┘ └───────────────┘
typ └───────┘ └─┘ └───────────────┘
3144
3145 @[simp] theorem card (n m : ℕ) : (Ico n m).card = m - n :=
id ┴ └─┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
src ┴ └─┘ └──┘ ┴ ┴
typ ┴ └─┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴
doc └──┘ └─┘ └──┘
3146 list.Ico.length _ _
id └─────────────┘
src └─────────────┘
typ └─────────────┘
3147
3148 theorem nodup (n m : ℕ) : nodup (Ico n m) := Ico.nodup _ _
id ┴ └───┘ └─┘ ┴ ┴ └───────┘
src ┴ └───┘ └─┘ └───────┘
typ ┴ └───┘ └─┘ ┴ ┴ └───────┘
doc └───┘ └─┘
3149
3150 @[simp] theorem mem {n m l : ℕ} : l ∈ Ico n m ↔ n ≤ l ∧ l < m :=
id ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ └─┘ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └─┘
3151 list.Ico.mem
id └──────────┘
src └──────────┘
typ └──────────┘
3152
3153 theorem eq_zero_of_le {n m : ℕ} (h : m ≤ n) : Ico n m = 0 :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
src ┴ ┴ └─┘ ┴
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
doc └─┘
3154 congr_arg coe $ list.Ico.eq_nil_of_le h
id └───────┘ └─┘ └───────────────────┘ ┴
src └───────┘ └─┘ └───────────────────┘
typ └───────┘ └─┘ └───────────────────┘ ┴
3155
3156 @[simp] theorem self_eq_zero {n : ℕ} : Ico n n = 0 :=
id ┴ └─┘ ┴ ┴ ┴
src ┴ └─┘ ┴
typ ┴ └─┘ ┴ ┴ ┴
doc └──┘ └─┘
3157 eq_zero_of_le $ le_refl n
id └───────────┘ └─────┘ ┴
src └───────────┘ └─────┘
typ └───────────┘ └─────┘ ┴
3158
3159 @[simp] theorem eq_zero_iff {n m : ℕ} : Ico n m = 0 ↔ m ≤ n :=
id ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └─┘ ┴ ┴ ┴
typ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc └──┘ └─┘
3160 iff.trans (coe_eq_zero _) list.Ico.eq_empty_iff
id └───────┘ └─────────┘ └───────────────────┘
src └───────┘ └─────────┘ └───────────────────┘
typ └───────┘ └─────────┘ └───────────────────┘
3161
3162 lemma add_consecutive {n m l : ℕ} (hnm : n ≤ m) (hml : m ≤ l) :
id ┴ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴ ┴ ┴
3163 Ico n m + Ico m l = Ico n l :=
id └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
src └─┘ ┴ └─┘ ┴ └─┘
typ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
doc └─┘ └─┘ └─┘
3164 congr_arg coe $ list.Ico.append_consecutive hnm hml
id └───────┘ └─┘ └─────────────────────────┘ └─┘ └─┘
src └───────┘ └─┘ └─────────────────────────┘
typ └───────┘ └─┘ └─────────────────────────┘ └─┘ └─┘
3165
3166 @[simp] lemma inter_consecutive (n m l : ℕ) : Ico n m ∩ Ico m l = 0 :=
id ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
src ┴ └─┘ ┴ └─┘ ┴
typ ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴
doc └──┘ └─┘ └─┘
3167 congr_arg coe $ list.Ico.bag_inter_consecutive n m l
id └───────┘ └─┘ └────────────────────────────┘ ┴ ┴ ┴
src └───────┘ └─┘ └────────────────────────────┘
typ └───────┘ └─┘ └────────────────────────────┘ ┴ ┴ ┴
3168
3169 @[simp] theorem succ_singleton {n : ℕ} : Ico n (n+1) = {n} :=
id ┴ └─┘ ┴ ┴┴ ┴ ┴┴
src ┴ └─┘ ┴ ┴ ┴
typ ┴ └─┘ ┴ ┴┴ ┴ ┴┴
doc └──┘ └─┘
3170 congr_arg coe $ list.Ico.succ_singleton
id └───────┘ └─┘ └─────────────────────┘
src └───────┘ └─┘ └─────────────────────┘
typ └───────┘ └─┘ └─────────────────────┘
3171
3172 theorem succ_top {n m : ℕ} (h : n ≤ m) : Ico n (m + 1) = m :: Ico n m :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └┘ └─┘ ┴ ┴
src ┴ ┴ └─┘ ┴ ┴ └┘ └─┘
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴ └┘ └─┘ ┴ ┴
doc └─┘ └┘ └─┘
3173 by rw [Ico, list.Ico.succ_top h, ← coe_add, add_comm]; refl
id └─┘ └───────────────┘ ┴ └─────┘ └──────┘
src └──┘└─┘└┘└───────────────┘┴ └──┘└─────┘└┘└──────┘┴ └────
typ └──┘└─┘└┘└───────────────┘┴┴└──┘└─────┘└┘└──────┘┴ └────
doc └──┘└─┘└┘ ┴ └──┘ └┘ ┴ └────
txt └──┘ └┘ ┴ └──┘ └┘ ┴ └────
par └──┘ └┘ ┴ └──┘ └┘ ┴ └────
pid └┘ └┘ ┴ └──┘ └┘ ┴ └
st └──────┘└───────────────────┘└─────────┘└────────┘┴└──────
3174
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
3175 theorem eq_cons {n m : ℕ} (h : n < m) : Ico n m = n :: Ico (n + 1) m :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ └┘ └─┘ ┴ ┴ ┴
src ┴ ┴ └─┘ ┴ └┘ └─┘ ┴
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ └┘ └─┘ ┴ ┴ ┴
doc └─┘ └┘ └─┘
3176 congr_arg coe $ list.Ico.eq_cons h
id └───────┘ └─┘ └──────────────┘ ┴
src └───────┘ └─┘ └──────────────┘
typ └───────┘ └─┘ └──────────────┘ ┴
3177
3178 @[simp] theorem pred_singleton {m : ℕ} (h : 0 < m) : Ico (m - 1) m = {m - 1} :=
id ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴┴ ┴
src ┴ ┴ └─┘ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴┴ ┴
doc └──┘ └─┘
3179 congr_arg coe $ list.Ico.pred_singleton h
id └───────┘ └─┘ └─────────────────────┘ ┴
src └───────┘ └─┘ └─────────────────────┘
typ └───────┘ └─┘ └─────────────────────┘ ┴
3180
3181 @[simp] theorem not_mem_top {n m : ℕ} : m ∉ Ico n m :=
id ┴ ┴ ┴ └─┘ ┴ ┴
src ┴ ┴ └─┘
typ ┴ ┴ ┴ └─┘ ┴ ┴
doc └──┘ └─┘
3182 list.Ico.not_mem_top
id └──────────────────┘
src └──────────────────┘
typ └──────────────────┘
3183
3184 lemma filter_lt_of_top_le {n m l : ℕ} (hml : m ≤ l) : (Ico n m).filter (λ x, x < l) = Ico n m :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
src ┴ ┴ └─┘ └────┘ ┴ ┴ └─┘
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
doc └─┘ └────┘ └─┘
3185 congr_arg coe $ list.Ico.filter_lt_of_top_le hml
id └───────┘ └─┘ └──────────────────────────┘ └─┘
src └───────┘ └─┘ └──────────────────────────┘
typ └───────┘ └─┘ └──────────────────────────┘ └─┘
3186
3187 lemma filter_lt_of_le_bot {n m l : ℕ} (hln : l ≤ n) : (Ico n m).filter (λ x, x < l) = ∅ :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ └─┘ └────┘ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └────┘
3188 congr_arg coe $ list.Ico.filter_lt_of_le_bot hln
id └───────┘ └─┘ └──────────────────────────┘ └─┘
src └───────┘ └─┘ └──────────────────────────┘
typ └───────┘ └─┘ └──────────────────────────┘ └─┘
3189
3190 lemma filter_lt_of_ge {n m l : ℕ} (hlm : l ≤ m) : (Ico n m).filter (λ x, x < l) = Ico n l :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
src ┴ ┴ └─┘ └────┘ ┴ ┴ └─┘
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
doc └─┘ └────┘ └─┘
3191 congr_arg coe $ list.Ico.filter_lt_of_ge hlm
id └───────┘ └─┘ └──────────────────────┘ └─┘
src └───────┘ └─┘ └──────────────────────┘
typ └───────┘ └─┘ └──────────────────────┘ └─┘
3192
3193 @[simp] lemma filter_lt (n m l : ℕ) : (Ico n m).filter (λ x, x < l) = Ico n (min m l) :=
id ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ └─┘ ┴ ┴
src ┴ └─┘ └────┘ ┴ ┴ └─┘ └─┘
typ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ └─┘ ┴ ┴
doc └──┘ └─┘ └────┘ └─┘
3194 congr_arg coe $ list.Ico.filter_lt n m l
id └───────┘ └─┘ └────────────────┘ ┴ ┴ ┴
src └───────┘ └─┘ └────────────────┘
typ └───────┘ └─┘ └────────────────┘ ┴ ┴ ┴
3195
3196 lemma filter_le_of_le_bot {n m l : ℕ} (hln : l ≤ n) : (Ico n m).filter (λ x, l ≤ x) = Ico n m :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
src ┴ ┴ └─┘ └────┘ ┴ ┴ └─┘
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
doc └─┘ └────┘ └─┘
3197 congr_arg coe $ list.Ico.filter_le_of_le_bot hln
id └───────┘ └─┘ └──────────────────────────┘ └─┘
src └───────┘ └─┘ └──────────────────────────┘
typ └───────┘ └─┘ └──────────────────────────┘ └─┘
3198
3199 lemma filter_le_of_top_le {n m l : ℕ} (hml : m ≤ l) : (Ico n m).filter (λ x, l ≤ x) = ∅ :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ ┴ └─┘ └────┘ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
doc └─┘ └────┘
3200 congr_arg coe $ list.Ico.filter_le_of_top_le hml
id └───────┘ └─┘ └──────────────────────────┘ └─┘
src └───────┘ └─┘ └──────────────────────────┘
typ └───────┘ └─┘ └──────────────────────────┘ └─┘
3201
3202 lemma filter_le_of_le {n m l : ℕ} (hnl : n ≤ l) : (Ico n m).filter (λ x, l ≤ x) = Ico l m :=
id ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
src ┴ ┴ └─┘ └────┘ ┴ ┴ └─┘
typ ┴ ┴ ┴ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ ┴ ┴
doc └─┘ └────┘ └─┘
3203 congr_arg coe $ list.Ico.filter_le_of_le hnl
id └───────┘ └─┘ └──────────────────────┘ └─┘
src └───────┘ └─┘ └──────────────────────┘
typ └───────┘ └─┘ └──────────────────────┘ └─┘
3204
3205 @[simp] lemma filter_le (n m l : ℕ) : (Ico n m).filter (λ x, l ≤ x) = Ico (max n l) m :=
id ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ └─┘ ┴ ┴ ┴
src ┴ └─┘ └────┘ ┴ ┴ └─┘ └─┘
typ ┴ └─┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └─┘ └─┘ ┴ ┴ ┴
doc └──┘ └─┘ └────┘ └─┘
3206 congr_arg coe $ list.Ico.filter_le n m l
id └───────┘ └─┘ └────────────────┘ ┴ ┴ ┴
src └───────┘ └─┘ └────────────────┘
typ └───────┘ └─┘ └────────────────┘ ┴ ┴ ┴
3207
3208 end Ico
3209
3210 variable (α)
3211
3212 def subsingleton_equiv [subsingleton α] : list α ≃ multiset α :=
id └──────────┘ ┴ └──┘ ┴ ┴ └──────┘ ┴
src └──────────┘ └──┘ ┴ └──────┘
typ └──────────┘ ┴ └──┘ ┴ ┴ └──────┘ ┴
doc ┴ └──────┘
3213 { to_fun := coe,
id └─┘
src └─┘
typ └─┘
3214 inv_fun := quot.lift id $ λ (a b : list α) (h : a ~ b),
id └───────┘ └┘ └──┘ ┴ ┴ ┴ ┴
src └┘ └──┘ ┴
typ └───────┘ └┘ └──┘ ┴ ┴ ┴ ┴
doc ┴
3215 list.ext_le (perm_length h) $ λ n h₁ h₂, subsingleton.elim _ _,
id └─────────┘ └─────────┘ ┴ ┴ └┘ └┘ └───────────────┘
src └─────────┘ └─────────┘ └───────────────┘
typ └─────────┘ └─────────┘ ┴ ┴ └┘ └┘ └───────────────┘
3216 left_inv := λ l, rfl,
id ┴ └─┘
src └─┘
typ ┴ └─┘
3217 right_inv := λ m, quot.induction_on m $ λ l, rfl }
id ┴ └───────────────┘ ┴ ┴ └─┘
src └───────────────┘ └─┘
typ ┴ └───────────────┘ ┴ ┴ └─┘
3218
3219 namespace nat
3220
3221 /-- The antidiagonal of a natural number `n` is
3222 the multiset of pairs `(i,j)` such that `i+j = n`. -/
3223 def antidiagonal (n : ℕ) : multiset (ℕ × ℕ) :=
id ┴ └──────┘ ┴ ┴ ┴
src ┴ └──────┘ ┴ ┴ ┴
typ ┴ └──────┘ ┴ ┴ ┴
doc └──────┘
3224 list.nat.antidiagonal n
id └───────────────────┘ ┴
src └───────────────────┘
typ └───────────────────┘ ┴
doc └───────────────────┘
3225
3226 /-- A pair (i,j) is contained in the antidiagonal of `n` if and only if `i+j=n`. -/
3227 @[simp] lemma mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} :
id ┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴
doc └──┘
3228 x ∈ antidiagonal n ↔ x.1 + x.2 = n :=
id ┴ ┴ └──────────┘ ┴ ┴ ┴┴ ┴ ┴┴ ┴ ┴
src ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ └──────────┘ ┴ ┴ ┴┴ ┴ ┴┴ ┴ ┴
doc └──────────┘
3229 by rw [antidiagonal, mem_coe, list.nat.mem_antidiagonal]
id └──────────┘ └─────┘ └───────────────────────┘
src └──┘└──────────┘└┘└─────┘└┘└───────────────────────┘└─
typ └──┘└──────────┘└┘└─────┘└┘└───────────────────────┘└─
doc └──┘└──────────┘└┘ └┘└───────────────────────┘└─
txt └──┘ └┘ └┘ └─
par └──┘ └┘ └┘ └─
pid └┘ └┘ └┘ ┴└
st └───────────────┘└───────┘└─────────────────────────┘┴└
3230
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
3231 /-- The cardinality of the antidiagonal of `n` is `n+1`. -/
3232 @[simp] lemma card_antidiagonal (n : ℕ) : (antidiagonal n).card = n+1 :=
id ┴ └──────────┘ ┴ └──┘ ┴ ┴┴
src ┴ └──────────┘ └──┘ ┴ ┴
typ ┴ └──────────┘ ┴ └──┘ ┴ ┴┴
doc └──┘ └──────────┘ └──┘
3233 by rw [antidiagonal, coe_card, list.nat.length_antidiagonal]
id └──────────┘ └──────┘ └──────────────────────────┘
src └──┘└──────────┘└┘└──────┘└┘└──────────────────────────┘└─
typ └──┘└──────────┘└┘└──────┘└┘└──────────────────────────┘└─
doc └──┘└──────────┘└┘ └┘└──────────────────────────┘└─
txt └──┘ └┘ └┘ └─
par └──┘ └┘ └┘ └─
pid └┘ └┘ └┘ ┴└
st └───────────────┘└────────┘└────────────────────────────┘┴└
3234
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
3235 /-- The antidiagonal of `0` is the list `[(0,0)]` -/
3236 @[simp] lemma antidiagonal_zero : antidiagonal 0 = {(0, 0)} :=
id └──────────┘ ┴ ┴┴
src └──────────┘ ┴ ┴┴
typ └──────────┘ ┴ ┴┴
doc └──┘ └──────────┘
3237 by { rw [antidiagonal, list.nat.antidiagonal_zero], refl }
id └──────────┘ └────────────────────────┘
src └──┘└──────────┘└┘└────────────────────────┘┴ └───┘
typ └──┘└──────────┘└┘└────────────────────────┘┴ └───┘
doc └──┘└──────────┘└┘└────────────────────────┘┴ └───┘
txt └──┘ └┘ ┴ └───┘
par └──┘ └┘ ┴ └───┘
pid └┘ └┘ ┴ ┴
st └─────────────────┘└──────────────────────────┘└──────┘└┘
3238
3239 /-- The antidiagonal of `n` does not contain duplicate entries. -/
3240 lemma nodup_antidiagonal (n : ℕ) : nodup (antidiagonal n) :=
id ┴ └───┘ └──────────┘ ┴
src ┴ └───┘ └──────────┘
typ ┴ └───┘ └──────────┘ ┴
doc └───┘ └──────────┘
3241 coe_nodup.2 $ list.nat.nodup_antidiagonal n
id └───────┘┴ └─────────────────────────┘ ┴
src └───────┘┴ └─────────────────────────┘
typ └───────┘┴ └─────────────────────────┘ ┴
doc └─────────────────────────┘
3242
3243 end nat
3244
3245 end multiset
3246
3247 @[to_additive]
doc └─────────┘
3248 theorem monoid_hom.map_multiset_prod [comm_monoid α] [comm_monoid β] (f : α →* β) (s : multiset α) :
id └─────────┘ ┴ └─────────┘ ┴ ┴ └┘ ┴ └──────┘ ┴
src └─────────┘ └─────────┘ └┘ └──────┘
typ └─────────┘ ┴ └─────────┘ ┴ ┴ └┘ ┴ └──────┘ ┴
doc └┘ └──────┘
3249 f s.prod = (s.map f).prod :=
id ┴ ┴└───┘ ┴ ┴└──┘ ┴ └──┘
src └───┘ ┴ └──┘ └──┘
typ ┴ ┴└───┘ ┴ ┴└──┘ ┴ └──┘
doc └───┘ └──┘ └──┘
3250 (s.prod_hom f).symm
id ┴└───────┘ ┴ └──┘
src └───────┘ └──┘
typ ┴└───────┘ ┴ └──┘